use of org.opengis.referencing.IdentifiedObject in project sis by apache.
the class IdentifiedObjectFinder method find.
/**
* Lookups objects which are approximatively equal to the specified object.
* The default implementation tries to instantiate some {@linkplain AbstractIdentifiedObject identified objects}
* from the authority factory specified at construction time, in the following order:
*
* <ul>
* <li>If the specified object contains {@linkplain AbstractIdentifiedObject#getIdentifiers() identifiers}
* associated to the same authority than the factory, then those identifiers are used for
* {@linkplain GeodeticAuthorityFactory#createObject(String) creating objects} to be tested.</li>
* <li>If the authority factory can create objects from their {@linkplain AbstractIdentifiedObject#getName() name}
* in addition of identifiers, then the name and {@linkplain AbstractIdentifiedObject#getAlias() aliases} are
* used for creating objects to be tested.</li>
* <li>If a full scan of the dataset is allowed, then full {@linkplain #getCodeCandidates set of candidate codes}
* is used for creating objects to be tested.</li>
* </ul>
*
* The created objects which are equal to the specified object in the
* the sense of {@link ComparisonMode#APPROXIMATIVE} are returned.
*
* @param object the object looked up.
* @return the identified objects, or an empty set if not found.
* @throws FactoryException if an error occurred while creating an object.
*/
public Set<IdentifiedObject> find(final IdentifiedObject object) throws FactoryException {
ArgumentChecks.ensureNonNull("object", object);
Set<IdentifiedObject> result = getFromCache(object);
if (result == null) {
final AuthorityFactoryProxy<?> previous = proxy;
proxy = AuthorityFactoryProxy.getInstance(object.getClass());
try {
if (!ignoreIdentifiers && !ignoreAxes) {
/*
* First check if one of the identifiers can be used to find directly an identified object.
* Verify that the object that we found is actually equal to given one; we do not blindly
* trust the identifiers in the user object.
*/
IdentifiedObject candidate = createFromIdentifiers(object);
if (candidate != null) {
// Not worth to cache.
return Collections.singleton(candidate);
}
/*
* We are unable to find the object from its identifiers. Try a quick name lookup.
* Some implementations like the one backed by the EPSG database are capable to find
* an object from its name.
*/
candidate = createFromNames(object);
if (candidate != null) {
// Not worth to cache.
return Collections.singleton(candidate);
}
}
/*
* Here we exhausted the quick paths.
* Perform a full scan (costly) if we are allowed to, otherwise abandon.
*/
if (domain == Domain.DECLARATION) {
// Do NOT cache.
return Collections.emptySet();
}
result = createFromCodes(object);
} finally {
proxy = previous;
}
// Costly operation (even if the result is empty) worth to cache.
result = cache(object, result);
}
return result;
}
use of org.opengis.referencing.IdentifiedObject in project sis by apache.
the class DefaultOperationMethod method getProperties.
/**
* Returns the properties to be given to an identified object derived from the specified one.
* This method returns the same properties than the supplied argument
* (as of <code>{@linkplain IdentifiedObjects#getProperties getProperties}(info)</code>),
* except for the following:
*
* <ul>
* <li>The {@linkplain IdentifiedObject#getName() name}'s authority is replaced by the specified one.</li>
* <li>All {@linkplain IdentifiedObject#getIdentifiers identifiers} are removed, because the new object
* to be created is probably not endorsed by the original authority.</li>
* </ul>
*
* This method returns a mutable map. Consequently, callers can add their own identifiers
* directly to this map if they wish.
*
* @param info the identified object to view as a properties map.
* @param authority the new authority for the object to be created,
* or {@code null} if it is not going to have any declared authority.
* @return the identified object properties in a mutable map.
*/
private static Map<String, Object> getProperties(final IdentifiedObject info, final Citation authority) {
final Map<String, Object> properties = new HashMap<>(IdentifiedObjects.getProperties(info));
properties.put(NAME_KEY, new NamedIdentifier(authority, info.getName().getCode()));
properties.remove(IDENTIFIERS_KEY);
return properties;
}
use of org.opengis.referencing.IdentifiedObject in project sis by apache.
the class ReferencingUtilities method getPropertiesForModifiedCRS.
/**
* Returns the properties of the given object but potentially with a modified name.
* Current implement truncates the name at the first non-white character which is not
* a valid Unicode identifier part, with the following exception:
*
* <ul>
* <li>If the character is {@code '('} and the content until the closing {@code ')'} is a valid
* Unicode identifier, then that part is included. The intent is to keep the prime meridian
* name in names like <cite>"NTF (Paris)"</cite>.</li>
* </ul>
*
* <div class="note"><b>Example:</b><ul>
* <li><cite>"NTF (Paris)"</cite> is left unchanged.</li>
* <li><cite>"WGS 84 (3D)"</cite> is truncated as <cite>"WGS 84"</cite>.</li>
* <li><cite>"Ellipsoidal 2D CS. Axes: latitude, longitude. Orientations: north, east. UoM: degree"</cite>
* is truncated as <cite>"Ellipsoidal 2D CS"</cite>.</li>
* </ul></div>
*
* @param object the identified object to view as a properties map.
* @return a view of the identified object properties.
*
* @see IdentifiedObjects#getProperties(IdentifiedObject, String...)
*
* @since 0.7
*/
public static Map<String, ?> getPropertiesForModifiedCRS(final IdentifiedObject object) {
final Map<String, ?> properties = IdentifiedObjects.getProperties(object, IdentifiedObject.IDENTIFIERS_KEY);
final Identifier id = (Identifier) properties.get(IdentifiedObject.NAME_KEY);
if (id != null) {
String name = id.getCode();
if (name != null) {
for (int i = 0; i < name.length(); ) {
final int c = name.codePointAt(i);
if (!Character.isUnicodeIdentifierPart(c) && !Character.isSpaceChar(c)) {
if (c == '(') {
final int endAt = name.indexOf(')', i);
if (endAt >= 0) {
final String extra = name.substring(i + 1, endAt);
if (CharSequences.isUnicodeIdentifier(extra)) {
i += extra.length() + 2;
}
}
}
name = CharSequences.trimWhitespaces(name, 0, i).toString();
if (!name.isEmpty()) {
final Map<String, Object> copy = new HashMap<>(properties);
copy.put(IdentifiedObject.NAME_KEY, name);
return copy;
}
}
i += Character.charCount(c);
}
}
}
return properties;
}
use of org.opengis.referencing.IdentifiedObject 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.opengis.referencing.IdentifiedObject 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