use of org.apache.sis.referencing.factory.IdentifiedObjectFinder in project sis by apache.
the class EPSGFactoryTest method testFindGeographic.
/**
* Tests {@link EPSGFactory#newIdentifiedObjectFinder()} method with a geographic CRS.
*
* @throws FactoryException if an error occurred while querying the factory.
*/
@Test
@DependsOnMethod("testWGS84")
public void testFindGeographic() throws FactoryException {
final EPSGFactory factory = TestFactorySource.factory;
assumeNotNull(factory);
final IdentifiedObjectFinder finder = factory.newIdentifiedObjectFinder();
final DefaultGeographicCRS crs = (DefaultGeographicCRS) CRS.fromWKT("GEOGCS[“WGS 84”,\n" + // Use the alias instead than primary name for forcing a deeper search.
" DATUM[“WGS 84”,\n" + // Different name for forcing a deeper search.
" SPHEROID[“WGS 1984”, 6378137.0, 298.257223563]],\n" + " PRIMEM[“Greenwich”, 0.0],\n" + " UNIT[“degree”, 0.017453292519943295],\n" + " AXIS[“Geodetic latitude”, NORTH],\n" + " AXIS[“Geodetic longitude”, EAST]]");
/*
* First, search for a CRS with axis order that does not match the ones in the EPSG database.
* IdentifiedObjectFinder should not accept EPSG:4326 as a match for the given CRS.
*/
assertEquals("Full scan should be enabled by default.", IdentifiedObjectFinder.Domain.VALID_DATASET, finder.getSearchDomain());
assertTrue("Should not find WGS84 because the axis order is not the same.", finder.find(crs.forConvention(AxesConvention.NORMALIZED)).isEmpty());
/*
* Ensure that the cache is empty.
*/
finder.setSearchDomain(IdentifiedObjectFinder.Domain.DECLARATION);
assertTrue("Should not find without a full scan, because the WKT contains no identifier " + "and the CRS name is ambiguous (more than one EPSG object have this name).", finder.find(crs).isEmpty());
/*
* Scan the database for searching the CRS.
*/
finder.setSearchDomain(IdentifiedObjectFinder.Domain.ALL_DATASET);
final IdentifiedObject found = finder.findSingleton(crs);
assertNotNull("With full scan allowed, the CRS should be found.", found);
assertEpsgNameAndIdentifierEqual("WGS 84", 4326, found);
/*
* Should find the CRS without the need of a full scan, because of the cache.
*/
finder.setSearchDomain(IdentifiedObjectFinder.Domain.DECLARATION);
assertSame("The CRS should still in the cache.", found, finder.findSingleton(crs));
}
use of org.apache.sis.referencing.factory.IdentifiedObjectFinder in project sis by apache.
the class AuthorityFactoriesTest method testFind.
/**
* Tests the {@code IdentifiedObjectFinder.find(…)} method.
*
* @throws FactoryException if the operation failed creation failed.
*/
@Test
public void testFind() throws FactoryException {
final CRSAuthorityFactory factory = AuthorityFactories.ALL;
final IdentifiedObjectFinder finder = AuthorityFactories.ALL.newIdentifiedObjectFinder();
final IdentifiedObject find = finder.findSingleton(HardCodedCRS.WGS84);
assertNotNull("With scan allowed, should find the CRS.", find);
assertTrue(HardCodedCRS.WGS84.equals(find, ComparisonMode.DEBUG));
assertSame(factory.createCoordinateReferenceSystem("CRS:84"), find);
}
use of org.apache.sis.referencing.factory.IdentifiedObjectFinder in project sis by apache.
the class IdentifiedObjects method lookupURN.
/**
* Looks up a URN, such as {@code "urn:ogc:def:crs:EPSG:9.1:4326"}, of the specified object.
* This method searches in all {@linkplain org.apache.sis.referencing.factory.GeodeticAuthorityFactory geodetic
* authority factories} known to SIS for an object {@linkplain org.apache.sis.util.ComparisonMode#APPROXIMATIVE
* approximatively equals} to the specified object. Then there is a choice:
*
* <ul>
* <li>If a single matching object is found in the specified authority factory, then its URN is returned.</li>
* <li>Otherwise if the given object is a {@link CompoundCRS} or {@link ConcatenatedOperation}
* and all components have an URN, then this method returns a combined URN.</li>
* <li>Otherwise this method returns {@code null}.</li>
* </ul>
*
* <p><strong>Note that this method checks the identifier validity.</strong>
* If the given object declares explicitly an identifier, then this method will instantiate an object from the
* authority factory using that identifier and compare it with the given object. If the comparison fails, then
* this method returns {@code null}. Consequently this method may return {@code null} even if the given object
* declares explicitly its identifier. If the declared identifier is wanted unconditionally,
* one can use the following pattern instead:
*
* {@preformat java
* String urn = toURN(object.getClass(), getIdentifier(object, authority));
* }
*
* This method can be seen as a converse of {@link CRS#forCode(String)}.
*
* @param object the object (usually a {@linkplain org.apache.sis.referencing.crs.AbstractCRS
* coordinate reference system}) whose identifier is to be found, or {@code null}.
* @param authority the authority for the identifier to return, or {@code null} for
* the first identifier regardless its authority.
* @return the identifier, or {@code null} if none was found without ambiguity or if the given object was null.
* @throws FactoryException if an error occurred during the search.
*
* @see #newFinder(String)
* @see #toURN(Class, Identifier)
*
* @since 0.7
*/
public static String lookupURN(final IdentifiedObject object, final Citation authority) throws FactoryException {
if (object == null) {
return null;
}
IdentifiedObjectFinder finder;
try {
finder = newFinder(Citations.getCodeSpace(authority));
} catch (NoSuchAuthorityFactoryException e) {
warning("lookupURN", e);
finder = newFinder(null);
}
String urn = lookupURN(object, authority, finder);
if (urn != null) {
return urn;
}
/*
* If we didn't found a URN but the given object is made of smaller components, build a combined URN.
* Example: "urn:ogc:def:crs, crs:EPSG::27700, crs:EPSG::5701" (without spaces actually).
*/
final List<? extends IdentifiedObject> components;
if (object instanceof CompoundCRS) {
components = CRS.getSingleComponents((CompoundCRS) object);
} else if (object instanceof ConcatenatedOperation) {
components = ((ConcatenatedOperation) object).getOperations();
} else {
return null;
}
StringBuilder buffer = null;
for (final IdentifiedObject component : components) {
urn = lookupURN(component, authority, finder);
if (urn == null) {
return null;
}
assert urn.startsWith(DefinitionURI.PREFIX) : urn;
if (buffer == null) {
buffer = new StringBuilder(40).append(DefinitionURI.PREFIX).append(DefinitionURI.SEPARATOR).append(NameMeaning.toObjectType(object.getClass()));
}
buffer.append(DefinitionURI.COMPONENT_SEPARATOR).append(urn, DefinitionURI.PREFIX.length() + 1, urn.length());
}
return (buffer != null) ? buffer.toString() : null;
}
use of org.apache.sis.referencing.factory.IdentifiedObjectFinder in project sis by apache.
the class DefinitionVerifier method withAuthority.
/**
* Compares the given CRS description with the authoritative description.
* The authoritative description is inferred from the identifier, if any.
*
* @param crs the CRS to compare with the authoritative description.
* @param factory the factory to use for fetching authoritative description, or {@code null} for the default.
* @param lookup whether this method is allowed to use {@link IdentifiedObjectFinder}.
* @return verification result, or {@code null} if the given CRS should be used as-is.
* @throws FactoryException if an error occurred while querying the authority factory.
*/
public static DefinitionVerifier withAuthority(final CoordinateReferenceSystem crs, final CRSAuthorityFactory factory, final boolean lookup) throws FactoryException {
final CoordinateReferenceSystem authoritative;
final Citation authority = (factory != null) ? factory.getAuthority() : null;
final String identifier = IdentifiedObjects.toString(IdentifiedObjects.getIdentifier(crs, authority));
if (identifier != null)
try {
/*
* An authority code was explicitly given in the CRS description. Create a CRS for that code
* (do not try to guess it). If the given code is unknown, we will report a warning and use
* the given CRS as-is.
*/
if (factory != null) {
authoritative = factory.createCoordinateReferenceSystem(identifier);
} else {
authoritative = CRS.forCode(identifier);
}
} catch (NoSuchAuthorityCodeException e) {
final DefinitionVerifier verifier = new DefinitionVerifier(crs);
verifier.arguments = new String[] { e.getLocalizedMessage() };
return verifier;
}
else if (lookup) {
/*
* No authority code was given in the CRS description. Try to guess the code with IdentifiedObjectFinder,
* ignoring axis order. If we can not guess a code or if we guess wrongly, use the given CRS silently
* (without reporting any warning) since there is apparently nothing wrong in the given CRS.
*/
final IdentifiedObjectFinder finder;
if (factory instanceof GeodeticAuthorityFactory) {
finder = ((GeodeticAuthorityFactory) factory).newIdentifiedObjectFinder();
} else {
finder = IdentifiedObjects.newFinder(Citations.getIdentifier(authority, false));
}
finder.setIgnoringAxes(true);
final IdentifiedObject ref = finder.findSingleton(crs);
if (ref instanceof CoordinateReferenceSystem) {
authoritative = (CoordinateReferenceSystem) ref;
} else {
// Found no identifier. Use the CRS as-is.
return null;
}
} else {
return null;
}
/*
* At this point we found an authoritative description (typically from EPSG database) for the given CRS.
* Verify if the given CRS is equal to the authoritative description, or a variant of it. The similarity
* variable tells us if we have equality (0), mismatch (-), or equality when using a variant (+).
*/
int similarity = 0;
final AbstractCRS ca = AbstractCRS.castOrCopy(authoritative);
AbstractCRS variant = ca;
while (!variant.equals(crs, ComparisonMode.APPROXIMATIVE)) {
if (similarity < VARIANTS.length) {
variant = ca.forConvention(VARIANTS[similarity++]);
} else if (identifier == null) {
// Mismatched CRS, but our "authoritative" description was only a guess. Ignore.
return null;
} else {
// Mismatched CRS and our authoritative description was not a guess. Need warning.
similarity = -1;
break;
}
}
final DefinitionVerifier verifier;
if (similarity > 0) {
/*
* Warning message (from Resources.properties):
*
* The coordinate system axes in the given “{0}” description do not conform to the expected axes
* according “{1}” authoritative description.
*/
verifier = new DefinitionVerifier(variant);
if (identifier != null) {
verifier.resourceKey = Resources.Keys.NonConformAxes_2;
verifier.arguments = new String[2];
}
} else {
verifier = new DefinitionVerifier(authoritative);
if (similarity != 0) {
/*
* Warning message (from Resources.properties):
*
* The given “{0}” description does not conform to the “{1}” authoritative description.
* Differences are found in {2,choice,0#method|1#conversion|2#coordinate system|3#datum|4#CRS}.
*/
verifier.resourceKey = Resources.Keys.NonConformCRS_3;
verifier.arguments = new Object[3];
verifier.arguments[2] = diffCode(CRS.getSingleComponents(authoritative).iterator(), CRS.getSingleComponents(crs).iterator());
}
}
if (verifier.arguments != null) {
verifier.arguments[0] = IdentifiedObjects.getName(crs, null);
verifier.arguments[1] = IdentifiedObjects.getIdentifierOrName(authoritative);
}
return verifier;
}
use of org.apache.sis.referencing.factory.IdentifiedObjectFinder in project sis by apache.
the class EPSGFactoryTest method testFindProjected.
/**
* Tests {@link EPSGFactory#newIdentifiedObjectFinder()} method with a projected CRS.
*
* @throws FactoryException if an error occurred while querying the factory.
*/
@Test
@DependsOnMethod("testFindGeographic")
public void testFindProjected() throws FactoryException {
final EPSGFactory factory = TestFactorySource.factory;
assumeNotNull(factory);
final IdentifiedObjectFinder finder = factory.newIdentifiedObjectFinder();
/*
* The PROJCS below intentionally uses a name different from the one found in the
* EPSG database, in order to force a full scan (otherwise the EPSG database would
* find it by name, but we want to test the scan).
*/
final CoordinateReferenceSystem crs = CRS.fromWKT("PROJCS[“Beijing 1954 (modified)”,\n" + " GEOGCS[“Beijing 1954 (modified)”,\n" + // Datum name matter.
" DATUM[“Beijing 1954”,\n" + // Intentional rounding error.
" SPHEROID[“Krassowsky 1940”, 6378245.00000006, 298.299999999998]],\n" + " PRIMEM[“Greenwich”, 0.0],\n" + " UNIT[“degree”, 0.017453292519943295],\n" + " AXIS[“Geodetic longitude”, EAST],\n" + // Wrong axis order, but should not block.
" AXIS[“Geodetic latitude”, NORTH]],\n" + " PROJECTION[“Transverse Mercator”],\n" + // Intentional rounding error.
" PARAMETER[“central_meridian”, 135.0000000000013],\n" + " PARAMETER[“latitude_of_origin”, 0.0],\n" + " PARAMETER[“scale_factor”, 1.0],\n" + // Intentional rounding error.
" PARAMETER[“false_easting”, 500000.000000004],\n" + " PARAMETER[“false_northing”, 0.0],\n" + " UNIT[“m”, 1.0],\n" + " AXIS[“Northing”, NORTH],\n" + " AXIS[“Easting”, EAST]]");
finder.setSearchDomain(IdentifiedObjectFinder.Domain.DECLARATION);
assertTrue("Should not find the CRS without a full scan.", finder.find(crs).isEmpty());
finder.setSearchDomain(IdentifiedObjectFinder.Domain.VALID_DATASET);
final Set<IdentifiedObject> find = finder.find(crs);
assertFalse("With full scan allowed, the CRS should be found.", find.isEmpty());
/*
* Both EPSG:2442 and EPSG:21463 defines the same projection with the same parameters
* and the same base GeographicCRS (EPSG:4214). The only difference I found was the
* area of validity...
*
* Note that there is also a EPSG:21483 code, but that one is deprecated and should
* not be selected in this test.
*/
final Iterator<IdentifiedObject> it = find.iterator();
assertEpsgNameAndIdentifierEqual("Beijing 1954 / 3-degree Gauss-Kruger CM 135E", 2442, it.next());
assertEpsgNameAndIdentifierEqual("Beijing 1954 / Gauss-Kruger CM 135E", 21463, it.next());
assertFalse("Expected no more element.", it.hasNext());
}
Aggregations