/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2003-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.referencing.factory.epsg;
import java.io.*;
import java.util.*;
import java.sql.SQLException;
import org.opengis.referencing.cs.*;
import org.opengis.referencing.crs.*;
import org.opengis.referencing.operation.*;
import org.opengis.util.FactoryException;
import org.apache.sis.referencing.crs.AbstractCRS;
import org.geotoolkit.factory.AuthorityFactoryFinder;
import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
import org.apache.sis.util.ComparisonMode;
import org.junit.*;
import static org.junit.Assume.assumeNotNull;
import static org.geotoolkit.referencing.Assert.*;
/**
* Tests transformations from CRS and/or operations created from the EPSG factory.
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Vadim Semenov
* @version 3.18
*/
public final strictfp class ThreadedEpsgFactoryTest extends EpsgFactoryTestBase {
/**
* Creates a test suite for the MS-Access database.
*/
public ThreadedEpsgFactoryTest() {
super();
}
/**
* Tests creations of operation objects.
*
* @throws FactoryException if an error occurred while querying the factory.
*/
@Test
public final void testCreationOperations() throws FactoryException {
assumeNotNull(factory);
final CoordinateOperationFactory opf = AuthorityFactoryFinder.getCoordinateOperationFactory(null);
CoordinateReferenceSystem sourceCRS, targetCRS;
CoordinateOperation operation;
sourceCRS = factory.createCoordinateReferenceSystem("4273");
targetCRS = factory.createCoordinateReferenceSystem("4979");
operation = opf.createOperation(sourceCRS, targetCRS);
assertNotSame(sourceCRS, targetCRS);
assertFalse(operation.getMathTransform().isIdentity());
assertSame(sourceCRS, factory.createCoordinateReferenceSystem("EPSG:4273"));
assertSame(targetCRS, factory.createCoordinateReferenceSystem("EPSG:4979"));
assertSame(sourceCRS, factory.createCoordinateReferenceSystem(" EPSG : 4273 "));
assertSame(targetCRS, factory.createCoordinateReferenceSystem(" EPSG : 4979 "));
/*
* CRS with "South along 180°" and "South along 90°E" axis.
*/
sourceCRS = factory.createCoordinateReferenceSystem("EPSG:32661");
targetCRS = factory.createCoordinateReferenceSystem("4326");
operation = opf.createOperation(sourceCRS, targetCRS);
final MathTransform transform = operation.getMathTransform();
final CoordinateSystem sourceCS = sourceCRS.getCoordinateSystem();
final CoordinateSystemAxis axis0 = sourceCS.getAxis(0);
final CoordinateSystemAxis axis1 = sourceCS.getAxis(1);
assertEquals("Northing", axis0.getName().getCode());
assertEquals("Easting", axis1.getName().getCode());
assertEquals("South along 180°", axis0.getDirection().name());
assertEquals("South along 90°E", axis1.getDirection().name());
assertFalse(transform.isIdentity());
// assertTrue(transform instanceof ConcatenatedTransform);
// ConcatenatedTransform ct = (ConcatenatedTransform) transform;
// /*
// * An affine transform for swapping axis should be performed after the map projection.
// */
// final int before = AffineTransform.TYPE_TRANSLATION |
// AffineTransform.TYPE_QUADRANT_ROTATION |
// AffineTransform.TYPE_UNIFORM_SCALE;
// final int after = AffineTransform.TYPE_FLIP |
// AffineTransform.TYPE_QUADRANT_ROTATION |
// AffineTransform.TYPE_UNIFORM_SCALE;
// assertTrue(ct.transform1 instanceof AffineTransform);
// assertEquals(before, ((AffineTransform) ct.transform1).getType());
// assertTrue(ct.transform2 instanceof ConcatenatedTransform);
// ct = (ConcatenatedTransform) ct.transform2;
// assertTrue(ct.transform1 instanceof AbstractMathTransform);
// assertTrue(ct.transform2 instanceof AffineTransform);
// assertEquals(after, ((AffineTransform) ct.transform2).getType());
}
/**
* Tests the serialization of many {@link CoordinateOperation} objects.
*
* @throws FactoryException if an error occurred while querying the factory.
* @throws IOException If an error occurred during the serialization process.
* @throws ClassNotFoundException Should never occur.
*/
@Test
@Ignore
public final void testSerialization() throws FactoryException, IOException, ClassNotFoundException {
assumeNotNull(factory);
CoordinateReferenceSystem crs1 = factory.createCoordinateReferenceSystem("4326");
CoordinateReferenceSystem crs2 = factory.createCoordinateReferenceSystem("4322");
CoordinateOperationFactory opf = AuthorityFactoryFinder.getCoordinateOperationFactory(null);
CoordinateOperation cop = opf.createOperation(crs1, crs2);
serialize(cop);
crs1 = crs2 = null;
final String crs1_name = "4326";
final int crs2_ranges[] = {4326, 4326,
/* [ 2] */ 4322, 4322,
/* [ 4] */ 4269, 4269,
/* [ 6] */ 4267, 4267,
/* [ 8] */ 4230, 4230,
/* [10] */ 32601, 32660,
/* [12] */ 32701, 32760,
/* [14] */ 2759, 2930};
for (int irange=0; irange<crs2_ranges.length; irange+=2) {
int range_start = crs2_ranges[irange ];
int range_end = crs2_ranges[irange+1];
for (int isystem2=range_start; isystem2<=range_end; isystem2++) {
if (crs1 == null) {
crs1 = factory.createCoordinateReferenceSystem(crs1_name);
}
String crs2_name = Integer.toString(isystem2);
crs2 = factory.createCoordinateReferenceSystem(crs2_name);
cop = opf.createOperation(crs1, crs2);
serialize(cop);
}
}
}
/**
* Tests the serialization of the specified object.
*/
private static void serialize(final Object object) throws IOException, ClassNotFoundException {
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(buffer)) {
out.writeObject(object);
}
final Object read;
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()))) {
read = in.readObject();
}
assertEquals(object, read);
assertEquals(object.hashCode(), read.hashCode());
}
/**
* Fetches the accuracy declared in all coordinate operations found in the database.
*
* @throws FactoryException if an error occurred while querying the factory.
*/
@Test
@Ignore
public final void testAccuracy() throws FactoryException {
assumeNotNull(factory);
final Set<String> identifiers = factory.getAuthorityCodes(CoordinateOperation.class);
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
double sum = 0;
int count = 0; // Number of coordinate operations (minus the skipped ones).
int created = 0; // Number of coordinate operations recognized by the factory.
int valid = 0; // Number of non-NaN accuracies.
for (final String code : identifiers) {
final CoordinateOperation operation;
count++;
try {
operation = factory.createCoordinateOperation(code);
} catch (FactoryException exception) {
// Skip unsupported coordinate operations, except if the cause is a SQL exception.
if (exception.getCause() instanceof SQLException) {
throw exception;
}
continue;
} catch (IllegalArgumentException exception) {
// TODO: we apparently have a bug with operation method 9633 (and others...).
if (!exception.getMessage().contains("Ordnance Survey National Transformation")) {
throw exception;
}
continue;
}
created++;
assertNotNull(operation);
final double accuracy = AbstractCoordinateOperation.castOrCopy(operation).getLinearAccuracy();
assertFalse(accuracy < 0);
if (!Double.isNaN(accuracy)) {
if (accuracy < min) min=accuracy;
if (accuracy > max) max=accuracy;
sum += accuracy;
valid++;
}
}
final PrintWriter out = ThreadedEpsgFactoryTest.out;
if (out != null) {
out.print("Number of coordinate operations: "); out.println(identifiers.size());
out.print("Number of tested operations: "); out.println(count);
out.print("Number of recognized operations: "); out.println(created);
out.print("Number of operations with accuracy: "); out.println(valid);
out.print("Minimal accuracy value (meters): "); out.println(min);
out.print("Maximal accuracy value (meters): "); out.println(max);
out.print("Average accuracy value (meters): "); out.println(sum / valid);
out.flush();
}
}
/**
* We are supposed to be able to get back identical {@link CoordinateReferenceSystem}
* objects when we create using the same definition. This test case ensures that we do
* get back identical objects when using an EPSG code and when using WKT.
* <p>
* The same definition is used in each case - will it work?
* Answer is no because we lost metadata information in WKT formatting;
* however two instances created with the same WKT work out okay.
*
* @throws FactoryException if an error occurred while querying the factory.
*/
@Test
@Ignore
public final void testUnique() throws FactoryException { // LGPL
assumeNotNull(factory);
final AbstractCRS epsgCrs = (AbstractCRS) CommonCRS.WGS84.geographic();
final String wkt = epsgCrs.toWKT();
final AbstractCRS wktCrs = (AbstractCRS) CRS.fromWKT(wkt);
assertTrue ("equals ignore metadata", epsgCrs.equals(wktCrs, ComparisonMode.APPROXIMATIVE));
assertTrue ("equals ignore metadata", epsgCrs.equals(wktCrs, ComparisonMode.IGNORE_METADATA));
assertFalse ("equals compare metadata", epsgCrs.equals(wktCrs, ComparisonMode.BY_CONTRACT));
assertFalse ("equals compare metadata", epsgCrs.equals(wktCrs, ComparisonMode.STRICT));
assertFalse ("equals", epsgCrs.equals(wktCrs));
assertNotSame("identity", epsgCrs, wktCrs);
// Parsing the same thing twice?
final AbstractCRS wktCrs2 = (AbstractCRS) CRS.fromWKT(wkt);
assertTrue ("equals ignore metadata", wktCrs.equals(wktCrs2, ComparisonMode.APPROXIMATIVE));
assertTrue ("equals ignore metadata", wktCrs.equals(wktCrs2, ComparisonMode.IGNORE_METADATA));
assertTrue ("equals compare metadata", wktCrs.equals(wktCrs2, ComparisonMode.BY_CONTRACT));
assertTrue ("equals compare metadata", wktCrs.equals(wktCrs2, ComparisonMode.STRICT));
assertEquals("equals", wktCrs, wktCrs2);
assertSame ("identity", wktCrs, wktCrs2);
}
}