Search in sources :

Example 16 with IdentifiedObject

use of org.opengis.referencing.IdentifiedObject in project sis by apache.

the class IdentifiedObjectFinder method createFromNames.

/**
 * Creates an object equals (optionally ignoring metadata), to the specified object using only the
 * {@linkplain AbstractIdentifiedObject#getName name} and {@linkplain AbstractIdentifiedObject#getAlias aliases}.
 * If no such object is found, returns {@code null}.
 *
 * <p>This method may be used with some {@linkplain GeodeticAuthorityFactory authority factory}
 * implementations like the one backed by the EPSG database, which are capable to find an object
 * from its name when the identifier is unknown.</p>
 *
 * @param  object  the object looked up.
 * @return the identified object, or {@code null} if not found.
 * @throws FactoryException if an error occurred while creating an object.
 *
 * @see #createFromCodes(IdentifiedObject)
 * @see #createFromIdentifiers(IdentifiedObject)
 */
private IdentifiedObject createFromNames(final IdentifiedObject object) throws FactoryException {
    String code = object.getName().getCode();
    IdentifiedObject candidate;
    try {
        candidate = create(code);
    } catch (FactoryException e) {
        /*
             * The identifier was not recognized. We will continue later with aliases.
             * Note: we catch a more generic exception than NoSuchAuthorityCodeException because
             *       this attempt may fail for various reasons (character string not supported
             *       by the underlying database for primary key, duplicated name found, etc.).
             */
        exceptionOccurred(e);
        candidate = null;
    }
    if (match(candidate, object)) {
        return candidate;
    }
    for (final GenericName id : object.getAlias()) {
        code = id.toString();
        try {
            candidate = create(code);
        } catch (FactoryException e) {
            // The name was not recognized. No problem, let's go on.
            exceptionOccurred(e);
            continue;
        }
        if (match(candidate, object)) {
            return candidate;
        }
    }
    return null;
}
Also used : GenericName(org.opengis.util.GenericName) FactoryException(org.opengis.util.FactoryException) IdentifiedObject(org.opengis.referencing.IdentifiedObject) AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject)

Example 17 with IdentifiedObject

use of org.opengis.referencing.IdentifiedObject in project sis by apache.

the class MetadataAssert method assertWktEquals.

/**
 * Asserts that the WKT of the given object according the given convention is equal to the expected one.
 * This method expected the {@code “…”} quotation marks instead of {@code "…"} for easier readability of
 * {@link String} constants in Java code.
 *
 * @param convention  the WKT convention to use.
 * @param expected    the expected text, or {@code null} if {@code object} is expected to be null.
 * @param object      the object to format in <cite>Well Known Text</cite> format, or {@code null}.
 */
public static void assertWktEquals(final Convention convention, final String expected, final Object object) {
    if (expected == null) {
        assertNull(object);
    } else {
        assertNotNull(object);
        final String wkt;
        synchronized (WKT_FORMAT) {
            WKT_FORMAT.setConvention(convention);
            wkt = WKT_FORMAT.format(object);
        }
        assertMultilinesEquals((object instanceof IdentifiedObject) ? ((IdentifiedObject) object).getName().getCode() : object.getClass().getSimpleName(), expected, wkt);
    }
}
Also used : InternationalString(org.opengis.util.InternationalString) IdentifiedObject(org.opengis.referencing.IdentifiedObject)

Example 18 with IdentifiedObject

use of org.opengis.referencing.IdentifiedObject in project sis by apache.

the class GeodeticObjectParser method parseMetadataAndClose.

/**
 * Parses an <strong>optional</strong> metadata elements and close.
 * This include elements like {@code "SCOPE"}, {@code "ID"} (WKT 2) or {@code "AUTHORITY"} (WKT 1).
 * This WKT 1 element has the following pattern:
 *
 * {@preformat wkt
 *     AUTHORITY["<name>", "<code>"]
 * }
 *
 * <div class="section">Fallback</div>
 * The name is a mandatory property, but some invalid WKT with an empty string exist. In such case,
 * we will use the name of the enclosed datum. Indeed, it is not uncommon to have the same name for
 * a geographic CRS and its geodetic datum.
 *
 * @param  parent    the parent element.
 * @param  name      the name of the parent object being parsed.
 * @param  fallback  the fallback to use if {@code name} is empty.
 * @return a properties map with the parent name and the optional authority code.
 * @throws ParseException if an element can not be parsed.
 */
@SuppressWarnings("ReturnOfCollectionOrArrayField")
private Map<String, Object> parseMetadataAndClose(final Element parent, final String name, final IdentifiedObject fallback) throws ParseException {
    properties.clear();
    properties.put(IdentifiedObject.NAME_KEY, (name.isEmpty() && fallback != null) ? fallback.getName() : name);
    Element element;
    while ((element = parent.pullElement(OPTIONAL, ID_KEYWORDS)) != null) {
        final String codeSpace = element.pullString("codeSpace");
        // Accepts Integer as well as String.
        final String code = element.pullObject("code").toString();
        // Accepts Number as well as String.
        final Object version = element.pullOptional(Object.class);
        final Element citation = element.pullElement(OPTIONAL, WKTKeywords.Citation);
        final String authority;
        if (citation != null) {
            authority = citation.pullString("authority");
            citation.close(ignoredElements);
        } else {
            authority = codeSpace;
        }
        final Element uri = element.pullElement(OPTIONAL, WKTKeywords.URI);
        if (uri != null) {
            // TODO: not yet stored, since often redundant with other informations.
            uri.pullString("URI");
            uri.close(ignoredElements);
        }
        element.close(ignoredElements);
        /*
             * Note: we could be tempted to assign the authority to the name as well, like below:
             *
             *     if (name instanceof String) {
             *         name = new NamedIdentifier(authority, (String) name);
             *     }
             *     properties.put(IdentifiedObject.NAME_KEY, name);
             *
             * However experience shows that it is often wrong in practice, because peoples often
             * declare EPSG codes but still use WKT names much shorter than the EPSG names
             * (for example "WGS84" for the datum instead than "World Geodetic System 1984"),
             * so the name in WKT is often not compliant with the name actually defined by the authority.
             */
        final ImmutableIdentifier id = new ImmutableIdentifier(Citations.fromName(authority), codeSpace, code, (version != null) ? version.toString() : null, null);
        final Object previous = properties.put(IdentifiedObject.IDENTIFIERS_KEY, id);
        if (previous != null) {
            Identifier[] identifiers;
            if (previous instanceof Identifier) {
                identifiers = new Identifier[] { (Identifier) previous, id };
            } else {
                identifiers = (Identifier[]) previous;
                final int n = identifiers.length;
                identifiers = Arrays.copyOf(identifiers, n + 1);
                identifiers[n] = id;
            }
            properties.put(IdentifiedObject.IDENTIFIERS_KEY, identifiers);
        // REMINDER: values associated to IDENTIFIERS_KEY shall be recognized by 'toIdentifier(Object)'.
        }
    }
    /*
         * Other metadata (SCOPE, AREA, etc.).  ISO 19162 said that at most one of each type shall be present,
         * but our parser accepts an arbitrary amount of some kinds of metadata. They can be recognized by the
         * 'while' loop.
         *
         * Most WKT do not contain any of those metadata, so we perform an 'isEmpty()' check as an optimization
         * for those common cases.
         */
    if (!parent.isEmpty()) {
        /*
             * Example: SCOPE["Large scale topographic mapping and cadastre."]
             */
        element = parent.pullElement(OPTIONAL, WKTKeywords.Scope);
        if (element != null) {
            // Other types like Datum use the same key.
            properties.put(ReferenceSystem.SCOPE_KEY, element.pullString("scope"));
            element.close(ignoredElements);
        }
        /*
             * Example: AREA["Netherlands offshore."]
             */
        DefaultExtent extent = null;
        while ((element = parent.pullElement(OPTIONAL, WKTKeywords.Area)) != null) {
            final String area = element.pullString("area");
            element.close(ignoredElements);
            if (extent == null) {
                extent = new DefaultExtent(area, null, null, null);
            } else {
                extent.getGeographicElements().add(new DefaultGeographicDescription(area));
            }
        }
        /*
             * Example: BBOX[51.43, 2.54, 55.77, 6.40]
             */
        while ((element = parent.pullElement(OPTIONAL, WKTKeywords.BBox)) != null) {
            final double southBoundLatitude = element.pullDouble("southBoundLatitude");
            final double westBoundLongitude = element.pullDouble("westBoundLongitude");
            final double northBoundLatitude = element.pullDouble("northBoundLatitude");
            final double eastBoundLongitude = element.pullDouble("eastBoundLongitude");
            element.close(ignoredElements);
            if (extent == null)
                extent = new DefaultExtent();
            extent.getGeographicElements().add(new DefaultGeographicBoundingBox(westBoundLongitude, eastBoundLongitude, southBoundLatitude, northBoundLatitude));
        }
        /*
             * Example: VERTICALEXTENT[-1000, 0, LENGTHUNIT[“metre”, 1]]
             *
             * Units are optional, default to metres (no "contextual units" here).
             */
        while ((element = parent.pullElement(OPTIONAL, WKTKeywords.VerticalExtent)) != null) {
            final double minimum = element.pullDouble("minimum");
            final double maximum = element.pullDouble("maximum");
            Unit<Length> unit = parseScaledUnit(element, WKTKeywords.LengthUnit, Units.METRE);
            element.close(ignoredElements);
            if (unit == null)
                unit = Units.METRE;
            if (extent == null)
                extent = new DefaultExtent();
            verticalElements = new VerticalInfo(verticalElements, extent, minimum, maximum, unit).resolve(verticalCRS);
        }
        /*
             * Example: TIMEEXTENT[2013-01-01, 2013-12-31]
             *
             * TODO: syntax like TIMEEXTENT[“Jurassic”, “Quaternary”] is not yet supported.
             * See https://issues.apache.org/jira/browse/SIS-163
             *
             * This operation requires the the sis-temporal module. If not available,
             * we will report a warning and leave the temporal extent missing.
             */
        while ((element = parent.pullElement(OPTIONAL, WKTKeywords.TimeExtent)) != null) {
            if (element.peekValue() instanceof String) {
                element.pullString("startTime");
                element.pullString("endTime");
                element.close(ignoredElements);
                warning(parent, element, Errors.formatInternational(Errors.Keys.UnsupportedType_1, "TimeExtent[String,String]"), null);
            } else {
                final Date startTime = element.pullDate("startTime");
                final Date endTime = element.pullDate("endTime");
                element.close(ignoredElements);
                try {
                    final DefaultTemporalExtent t = new DefaultTemporalExtent();
                    t.setBounds(startTime, endTime);
                    if (extent == null)
                        extent = new DefaultExtent();
                    extent.getTemporalElements().add(t);
                } catch (UnsupportedOperationException e) {
                    warning(parent, element, null, e);
                }
            }
        }
        if (extent != null) {
            properties.put(ReferenceSystem.DOMAIN_OF_VALIDITY_KEY, extent);
        }
        /*
             * Example: REMARK["Замечание на русском языке"]
             */
        element = parent.pullElement(OPTIONAL, WKTKeywords.Remark);
        if (element != null) {
            properties.put(IdentifiedObject.REMARKS_KEY, element.pullString("remarks"));
            element.close(ignoredElements);
        }
    }
    parent.close(ignoredElements);
    return properties;
}
Also used : Date(java.util.Date) DefaultGeographicDescription(org.apache.sis.metadata.iso.extent.DefaultGeographicDescription) ImmutableIdentifier(org.apache.sis.metadata.iso.ImmutableIdentifier) ReferenceIdentifier(org.opengis.referencing.ReferenceIdentifier) Identifier(org.opengis.metadata.Identifier) DefaultGeographicBoundingBox(org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox) DefaultExtent(org.apache.sis.metadata.iso.extent.DefaultExtent) Length(javax.measure.quantity.Length) DefaultTemporalExtent(org.apache.sis.metadata.iso.extent.DefaultTemporalExtent) IdentifiedObject(org.opengis.referencing.IdentifiedObject) ImmutableIdentifier(org.apache.sis.metadata.iso.ImmutableIdentifier)

Example 19 with IdentifiedObject

use of org.opengis.referencing.IdentifiedObject in project sis by apache.

the class IdentifiedObjectFormat method format.

/**
 * Formats the given object.
 */
@Override
public StringBuffer format(final Object obj, final StringBuffer toAppendTo, final FieldPosition pos) {
    final ReferenceIdentifier identifier = ((IdentifiedObject) obj).getName();
    if (identifier == null) {
        return toAppendTo.append(Vocabulary.getResources(locale).getString(Vocabulary.Keys.Unnamed));
    }
    if (identifier instanceof GenericName) {
        // The toString() behavior is specified by the GenericName javadoc.
        return toAppendTo.append(((GenericName) identifier).toInternationalString().toString(locale));
    }
    final String code = identifier.getCode();
    String cs = identifier.getCodeSpace();
    if (cs == null || cs.isEmpty()) {
        cs = Citations.getIdentifier(identifier.getAuthority(), true);
    }
    if (cs != null) {
        toAppendTo.append(cs).append(Citations.DEFAULT_SEPARATOR);
    }
    return toAppendTo.append(code);
}
Also used : GenericName(org.opengis.util.GenericName) ReferenceIdentifier(org.opengis.referencing.ReferenceIdentifier) IdentifiedObject(org.opengis.referencing.IdentifiedObject)

Example 20 with IdentifiedObject

use of org.opengis.referencing.IdentifiedObject in project sis by apache.

the class ReferencingFunctions method getGeographicArea.

/**
 * Returns the domain of validity as a geographic bounding box for an identified object.
 * This method returns a 2×2 matrix:
 * the first row contains the latitude and longitude of upper left corner,
 * and the second row contains the latitude and longitude of bottom right corner.
 * Units are degrees.
 *
 * @param  codeOrPath  the code allocated by an authority, or the path to a file.
 * @return the object bounding box.
 */
@Override
public double[][] getGeographicArea(final String codeOrPath) {
    final CacheKey<GeographicBoundingBox> key = new CacheKey<>(GeographicBoundingBox.class, codeOrPath, null, null);
    GeographicBoundingBox area = key.peek();
    if (area == null) {
        final Cache.Handler<GeographicBoundingBox> handler = key.lock();
        try {
            area = handler.peek();
            if (area == null)
                try {
                    final IdentifiedObject object = getIdentifiedObject(codeOrPath, null);
                    final Object domain = IdentifiedObjects.getProperties(object).get(ReferenceSystem.DOMAIN_OF_VALIDITY_KEY);
                    if (domain instanceof Extent) {
                        area = Extents.getGeographicBoundingBox((Extent) domain);
                    }
                } catch (Exception exception) {
                    reportException("getGeographicArea", exception);
                }
        } finally {
            handler.putAndUnlock(area);
        }
    }
    if (area == null) {
        return new double[][] {};
    }
    return new double[][] { new double[] { area.getNorthBoundLatitude(), area.getWestBoundLongitude() }, new double[] { area.getSouthBoundLatitude(), area.getEastBoundLongitude() } };
}
Also used : Extent(org.opengis.metadata.extent.Extent) IdentifiedObject(org.opengis.referencing.IdentifiedObject) AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) GeographicBoundingBox(org.opengis.metadata.extent.GeographicBoundingBox) IdentifiedObject(org.opengis.referencing.IdentifiedObject) AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) DataStoreException(org.apache.sis.storage.DataStoreException) IllegalArgumentException(com.sun.star.lang.IllegalArgumentException) FactoryException(org.opengis.util.FactoryException) Cache(org.apache.sis.util.collection.Cache)

Aggregations

IdentifiedObject (org.opengis.referencing.IdentifiedObject)30 AbstractIdentifiedObject (org.apache.sis.referencing.AbstractIdentifiedObject)15 InternationalString (org.opengis.util.InternationalString)10 FactoryException (org.opengis.util.FactoryException)8 IllegalArgumentException (com.sun.star.lang.IllegalArgumentException)5 IdentifiedObjectFinder (org.apache.sis.referencing.factory.IdentifiedObjectFinder)5 DataStoreException (org.apache.sis.storage.DataStoreException)5 Identifier (org.opengis.metadata.Identifier)5 ReferenceIdentifier (org.opengis.referencing.ReferenceIdentifier)5 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)5 HashMap (java.util.HashMap)4 Cache (org.apache.sis.util.collection.Cache)3 Test (org.junit.Test)3 GenericName (org.opengis.util.GenericName)3 NameToIdentifier (org.apache.sis.internal.metadata.NameToIdentifier)2 FormattableObject (org.apache.sis.io.wkt.FormattableObject)2 NamedIdentifier (org.apache.sis.referencing.NamedIdentifier)2 DependsOnMethod (org.apache.sis.test.DependsOnMethod)2 SimpleInternationalString (org.apache.sis.util.iso.SimpleInternationalString)2 Extent (org.opengis.metadata.extent.Extent)2