Search in sources :

Example 56 with Identifier

use of org.opengis.metadata.Identifier in project sis by apache.

the class ProvidersTest method ensureParameterUniqueness.

/**
 * Ensures that every parameter instance is unique. Actually this test is not strong requirement.
 * This is only for sharing existing resources by avoiding unnecessary objects duplication.
 *
 * @throws ReflectiveOperationException if the instantiation of a service provider failed.
 */
@Test
public void ensureParameterUniqueness() throws ReflectiveOperationException {
    final Map<GeneralParameterDescriptor, String> groupNames = new IdentityHashMap<>();
    final Map<GeneralParameterDescriptor, GeneralParameterDescriptor> parameters = new HashMap<>();
    final Map<Object, Object> namesAndIdentifiers = new HashMap<>();
    for (final Class<?> c : methods()) {
        final OperationMethod method = (OperationMethod) c.newInstance();
        final ParameterDescriptorGroup group = method.getParameters();
        final String operationName = group.getName().getCode();
        for (final GeneralParameterDescriptor param : group.descriptors()) {
            assertFalse("Parameter declared twice in the same group.", operationName.equals(groupNames.put(param, operationName)));
            /*
                 * Ensure uniqueness of the parameter descriptor as a whole.
                 */
            final Identifier name = param.getName();
            Object existing = parameters.put(param, param);
            if (existing != null && existing != param) {
                fail("Parameter “" + name.getCode() + "” defined in “" + operationName + '”' + " was already defined in “" + groupNames.get(existing) + "”." + " The same instance could be shared.");
            }
            /*
                 * Ensure uniqueness of each name and identifier.
                 */
            existing = namesAndIdentifiers.put(name, name);
            if (existing != null && existing != name) {
                fail("The name of parameter “" + name.getCode() + "” defined in “" + operationName + '”' + " was already defined elsewhere. The same instance could be shared.");
            }
            for (final GenericName alias : param.getAlias()) {
                existing = namesAndIdentifiers.put(alias, alias);
                if (existing != null && existing != alias) {
                    fail("Alias “" + alias + "” of parameter “" + name.getCode() + "” defined in “" + operationName + '”' + " was already defined elsewhere. The same instance could be shared.");
                }
            }
            for (final Identifier id : param.getIdentifiers()) {
                existing = namesAndIdentifiers.put(id, id);
                if (existing != null && existing != id) {
                    fail("Identifier “" + id + "” of parameter “" + name.getCode() + "” defined in “" + operationName + '”' + " was already defined elsewhere. The same instance could be shared.");
                }
            }
        }
    }
}
Also used : IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) IdentityHashMap(java.util.IdentityHashMap) ParameterDescriptorGroup(org.opengis.parameter.ParameterDescriptorGroup) GeneralParameterDescriptor(org.opengis.parameter.GeneralParameterDescriptor) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) OperationMethod(org.opengis.referencing.operation.OperationMethod) GenericName(org.opengis.util.GenericName) Identifier(org.opengis.metadata.Identifier) Test(org.junit.Test)

Example 57 with Identifier

use of org.opengis.metadata.Identifier in project sis by apache.

the class DefaultAggregateInformation method setAggregateDataSetIdentifier.

/**
 * Sets the identification information about aggregate dataset.
 *
 * @param  newValue  the new identifier.
 *
 * @deprecated As of ISO 19115:2014, replaced by an identifier of {@link #getAggregateDataSetName()}.
 */
@Deprecated
public void setAggregateDataSetIdentifier(final Identifier newValue) {
    checkWritePermission();
    Citation name = getAggregateDataSetName();
    if (newValue != null) {
        if (!(name instanceof DefaultCitation)) {
            name = new DefaultCitation(name);
            setAggregateDataSetName(name);
        }
        /*
             * If there is more than one value, replace only the first one and keep all other ones unchanged.
             * The intent is to be consistent with the getter method, which returns the first element.
             */
        final ArrayList<Identifier> identifiers = new ArrayList<>(name.getIdentifiers());
        if (identifiers.isEmpty()) {
            identifiers.add(newValue);
        } else {
            identifiers.set(0, newValue);
        }
        ((DefaultCitation) name).setIdentifiers(identifiers);
    } else if (name != null) {
        final Iterator<? extends Identifier> it = name.getIdentifiers().iterator();
        if (it.hasNext()) {
            it.next();
            it.remove();
        }
    }
}
Also used : Identifier(org.opengis.metadata.Identifier) DefaultCitation(org.apache.sis.metadata.iso.citation.DefaultCitation) ArrayList(java.util.ArrayList) Iterator(java.util.Iterator) Citation(org.opengis.metadata.citation.Citation) DefaultCitation(org.apache.sis.metadata.iso.citation.DefaultCitation)

Example 58 with Identifier

use of org.opengis.metadata.Identifier in project sis by apache.

the class Proj4 method definition.

/**
 * Infers a {@literal Proj.4} definition from the given projected, geographic or geocentric coordinate reference system.
 * This method does not need the Proj.4 native library; it can be used in a pure Java application.
 * However the returned definition string may differ depending on whether the Proj.4 library is available or not.
 *
 * @param  crs  the coordinate reference system for which to create a Proj.4 definition.
 * @return the definition of the given CRS in a Proj.4 format.
 * @throws FactoryException if the Proj.4 definition string can not be created from the given CRS.
 */
public static String definition(final CoordinateReferenceSystem crs) throws FactoryException {
    ArgumentChecks.ensureNonNull("crs", crs);
    /*
         * If the given CRS object is associated to a Proj.4 structure, let Proj.4 formats itself
         * the definition string. Note that this operation may fail if there is no Proj.4 library
         * in the current system, or no JNI bindings to that library.
         */
    try {
        for (final Identifier id : crs.getIdentifiers()) {
            if (id instanceof PJ) {
                return ((PJ) id).getCode();
            }
        }
    } catch (UnsatisfiedLinkError e) {
        // Thrown the first time that we try to use the library.
        Logging.unexpectedException(Logging.getLogger(Modules.GDAL), Proj4.class, "definition", e);
    } catch (NoClassDefFoundError e) {
        // Thrown on all attempts after the first one.
        Logging.recoverableException(Logging.getLogger(Modules.GDAL), Proj4.class, "definition", e);
    }
    /*
         * If we found no Proj.4 structure, formats the definition string ourself. The string may differ from
         * what Proj.4 would have given. In particular, we do not provide "+init=" or "+datum=" parameter.
         * But the definition should still be semantically equivalent.
         */
    final String method;
    final GeodeticDatum datum;
    final ParameterValueGroup parameters;
    final CoordinateSystem cs = crs.getCoordinateSystem();
    if (crs instanceof GeodeticCRS) {
        if (cs instanceof EllipsoidalCS) {
            method = "latlon";
        } else if (cs instanceof CartesianCS) {
            method = "geocent";
        } else {
            throw new FactoryException(Errors.format(Errors.Keys.UnsupportedCoordinateSystem_1, cs.getClass()));
        }
        datum = ((GeodeticCRS) crs).getDatum();
        parameters = null;
    } else if (crs instanceof ProjectedCRS) {
        Projection c = ((ProjectedCRS) crs).getConversionFromBase();
        datum = ((ProjectedCRS) crs).getDatum();
        method = name(c.getMethod());
        parameters = c.getParameterValues();
    } else {
        throw new FactoryException(Errors.format(Errors.Keys.UnsupportedType_1, crs.getClass()));
    }
    /*
         * Append the map projection parameters. Those parameters may include axis lengths (a and b),
         * but not necessarily. If axis lengths are specified, then we will ignore the Ellipsoid instance
         * associated to the CRS.
         */
    final StringBuilder definition = new StringBuilder(100);
    definition.append(Proj4Factory.PROJ_PARAM).append(method);
    boolean hasSemiMajor = false;
    boolean hasSemiMinor = false;
    if (parameters != null) {
        definition.append(Proj4Factory.STANDARD_OPTIONS);
        for (final GeneralParameterValue parameter : parameters.values()) {
            if (parameter instanceof ParameterValue<?>) {
                final ParameterValue<?> pv = (ParameterValue<?>) parameter;
                final Object value;
                Unit<?> unit = pv.getUnit();
                if (unit != null) {
                    unit = Units.isAngular(unit) ? Units.DEGREE : unit.getSystemUnit();
                    // Always in metres or degrees.
                    value = pv.doubleValue(unit);
                } else {
                    value = pv.getValue();
                    if (value == null) {
                        continue;
                    }
                }
                final String pn = name(parameter.getDescriptor());
                hasSemiMajor |= pn.equals("a");
                hasSemiMinor |= pn.equals("b");
                definition.append(" +").append(pn).append('=').append(value);
            }
        }
    }
    /*
         * Append datum information: axis lengths if they were not part of the parameters, then prime meridian.
         */
    final Ellipsoid ellipsoid = datum.getEllipsoid();
    if (!hasSemiMajor)
        definition.append(" +a=").append(ellipsoid.getSemiMajorAxis());
    if (!hasSemiMinor)
        definition.append(" +b=").append(ellipsoid.getSemiMinorAxis());
    final PrimeMeridian pm = datum.getPrimeMeridian();
    if (pm != null) {
        double lon = pm.getGreenwichLongitude();
        final Unit<Angle> unit = pm.getAngularUnit();
        if (unit != null) {
            lon = unit.getConverterTo(Units.DEGREE).convert(lon);
        }
        definition.append(" +pm=").append(lon);
    }
    /*
         * Appends axis directions. This method always format a vertical direction (up or down)
         * even if the coordinate system is two-dimensional, because Proj.4 seems to require it.
         * Also extract axis units in the process.
         */
    // Horizontal at index 0, vertical at index 1.
    final Unit<?>[] units = new Unit<?>[2];
    boolean validCS = true;
    definition.append(' ').append(Proj4Factory.AXIS_ORDER_PARAM);
    final int dimension = Math.min(cs.getDimension(), 3);
    boolean hasVertical = false;
    for (int i = 0; i < dimension; i++) {
        final CoordinateSystemAxis axis = cs.getAxis(i);
        final AxisDirection dir = axis.getDirection();
        int unitIndex = 0;
        if (!AxisDirections.isCardinal(dir)) {
            if (!AxisDirections.isVertical(dir)) {
                throw new FactoryException(Errors.format(Errors.Keys.UnsupportedAxisDirection_1, dir));
            }
            hasVertical = true;
            unitIndex = 1;
        }
        final Unit<?> old = units[unitIndex];
        units[unitIndex] = axis.getUnit();
        validCS &= (old == null || old.equals(units[unitIndex]));
        definition.appendCodePoint(Character.toLowerCase(dir.name().codePointAt(0)));
    }
    if (!hasVertical && dimension < 3) {
        // Add a UP direction if not already present.
        definition.append('u');
    }
    /*
         * Append units of measurement, then verify the coordinate system validity.
         */
    for (int i = 0; i < units.length; i++) {
        final Unit<?> unit = units[i];
        if (unit != null && !unit.equals(Units.DEGREE) && !unit.equals(Units.METRE)) {
            validCS &= Units.isLinear(unit);
            definition.append(" +");
            // "+vto_meter" parameter.
            if (i == 1)
                definition.append('v');
            definition.append("to_meter=").append(Units.toStandardUnit(unit));
        }
    }
    /*
         * Append the "+towgs84" element if any. This is the last piece of information.
         * Note that the use of a "+towgs84" parameter is an "early binding" approach,
         * which is usually not recommended. But Proj4 works that way.
         */
    if (validCS) {
        if (datum instanceof DefaultGeodeticDatum) {
            for (final BursaWolfParameters bwp : ((DefaultGeodeticDatum) datum).getBursaWolfParameters()) {
                if (Utilities.equalsIgnoreMetadata(CommonCRS.WGS84.datum(), bwp.getTargetDatum())) {
                    definition.append(" +towgs84=").append(bwp.tX).append(',').append(bwp.tY).append(',').append(bwp.tZ);
                    if (!bwp.isTranslation()) {
                        definition.append(',').append(bwp.rX).append(',').append(bwp.rY).append(',').append(bwp.rZ).append(',').append(bwp.dS);
                    }
                    break;
                }
            }
        }
        return definition.toString();
    }
    /*
         * If we reach this point, we detected a coordinate system that we can not format as a
         * Proj.4 definition string. Format an error message with axis directions and units.
         */
    definition.setLength(0);
    definition.append('(');
    for (int i = 0; i < units.length; i++) {
        final CoordinateSystemAxis axis = cs.getAxis(i);
        if (i != 0)
            definition.append(", ");
        definition.append(axis.getUnit()).append(' ').append(Types.getCodeName(axis.getDirection()));
    }
    throw new FactoryException(Errors.format(Errors.Keys.IllegalCoordinateSystem_1, definition.append(')')));
}
Also used : ParameterValueGroup(org.opengis.parameter.ParameterValueGroup) UnavailableFactoryException(org.apache.sis.referencing.factory.UnavailableFactoryException) FactoryException(org.opengis.util.FactoryException) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) Projection(org.opengis.referencing.operation.Projection) CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis) Unit(javax.measure.Unit) Identifier(org.opengis.metadata.Identifier) AxisDirection(org.opengis.referencing.cs.AxisDirection) EllipsoidalCS(org.opengis.referencing.cs.EllipsoidalCS) CartesianCS(org.opengis.referencing.cs.CartesianCS) GeneralParameterValue(org.opengis.parameter.GeneralParameterValue) ParameterValue(org.opengis.parameter.ParameterValue) GeneralParameterValue(org.opengis.parameter.GeneralParameterValue) GeodeticDatum(org.opengis.referencing.datum.GeodeticDatum) DefaultGeodeticDatum(org.apache.sis.referencing.datum.DefaultGeodeticDatum) GeodeticCRS(org.opengis.referencing.crs.GeodeticCRS) PrimeMeridian(org.opengis.referencing.datum.PrimeMeridian) ProjectedCRS(org.opengis.referencing.crs.ProjectedCRS) Angle(javax.measure.quantity.Angle) DefaultGeodeticDatum(org.apache.sis.referencing.datum.DefaultGeodeticDatum) IdentifiedObject(org.opengis.referencing.IdentifiedObject) BursaWolfParameters(org.apache.sis.referencing.datum.BursaWolfParameters) Ellipsoid(org.opengis.referencing.datum.Ellipsoid)

Example 59 with Identifier

use of org.opengis.metadata.Identifier in project sis by apache.

the class Proj4Factory method createOperation.

/**
 * Creates an operation for conversion or transformation between two coordinate reference systems.
 * The given CRSs should be instances {@linkplain #createCoordinateReferenceSystem created by this factory}.
 * If not, then there is a choice:
 *
 * <ul>
 *   <li>If {@code force} is {@code false}, then this method returns {@code null}.</li>
 *   <li>Otherwise this method always uses Proj.4 for performing the coordinate operations,
 *       regardless if the given CRS were created from Proj.4 definition strings or not.
 *       This method fails if it can not map the given CRS to Proj.4 data structures.</li>
 * </ul>
 *
 * @param  sourceCRS  the source coordinate reference system.
 * @param  targetCRS  the target coordinate reference system.
 * @param  force      whether to force the creation of a Proj.4 transform
 *                    even if the given CRS are not wrappers around Proj.4 data structures.
 * @return a coordinate operation for transforming coordinates from the given source CRS to the given target CRS, or
 *         {@code null} if the given CRS are not wrappers around Proj.4 data structures and {@code force} is false.
 * @throws FactoryException if {@code force} is {@code true} and this method can not create Proj.4 transform
 *         for the given pair of coordinate reference systems.
 *
 * @see Proj4#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, boolean)
 * @see DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem)
 */
public CoordinateOperation createOperation(final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS, final boolean force) throws FactoryException {
    final PJ source, target;
    try {
        if ((source = unwrapOrCreate(sourceCRS, force)) == null || (target = unwrapOrCreate(targetCRS, force)) == null) {
            // At least one CRS is not a Proj.4 wrapper and 'force' is false.
            return null;
        }
    } catch (UnsatisfiedLinkError | NoClassDefFoundError e) {
        throw new UnavailableFactoryException(Proj4.unavailable(e), e);
    }
    /*
         * Before to create a transform, verify if the target CRS already contains a suitable transform.
         * In such case, returning the existing operation is preferable since it usually contains better
         * parameter description than what this method build.
         */
    if (targetCRS instanceof GeneralDerivedCRS) {
        final CoordinateOperation op = ((GeneralDerivedCRS) targetCRS).getConversionFromBase();
        final MathTransform tr = op.getMathTransform();
        if (tr instanceof Transform && ((Transform) tr).isFor(sourceCRS, source, targetCRS, target)) {
            return op;
        }
    }
    /*
         * The 'Transform' construction implies parameter validation, so we do it first before to
         * construct other objects.
         */
    final Transform tr = new Transform(source, is3D("sourceCRS", sourceCRS), target, is3D("targetCRS", targetCRS));
    Identifier id;
    String src = null, tgt = null, name = UNNAMED;
    if ((id = sourceCRS.getName()) != null)
        src = id.getCode();
    if ((id = targetCRS.getName()) != null)
        tgt = id.getCode();
    if (src != null || tgt != null) {
        final StringBuilder buffer = new StringBuilder();
        if (src != null)
            buffer.append("From ").append(src);
        if (tgt != null)
            buffer.append(buffer.length() == 0 ? "To " : " to ").append(tgt);
        name = buffer.toString();
    }
    return opFactory().createSingleOperation(identifier(name), sourceCRS, targetCRS, null, Transform.METHOD, tr);
}
Also used : ImmutableIdentifier(org.apache.sis.metadata.iso.ImmutableIdentifier) Identifier(org.opengis.metadata.Identifier) SimpleInternationalString(org.apache.sis.util.iso.SimpleInternationalString) UnavailableFactoryException(org.apache.sis.referencing.factory.UnavailableFactoryException)

Example 60 with Identifier

use of org.opengis.metadata.Identifier in project sis by apache.

the class Proj4Factory method identifier.

/**
 * Returns the identifier for the given code in {@literal Proj.4} namespace.
 */
private Map<String, Object> identifier(final String code) {
    Identifier id = identifiers.computeIfAbsent(code, (k) -> {
        short i18n = 0;
        if (k.equalsIgnoreCase(UNNAMED))
            i18n = Vocabulary.Keys.Unnamed;
        if (k.equalsIgnoreCase("Unknown"))
            i18n = Vocabulary.Keys.Unknown;
        return new ImmutableIdentifier(Citations.PROJ4, Constants.PROJ4, k, null, (i18n != 0) ? Vocabulary.formatInternational(i18n) : null);
    });
    final Map<String, Object> properties = new HashMap<>(defaultProperties);
    properties.put(IdentifiedObject.NAME_KEY, id);
    return properties;
}
Also used : ImmutableIdentifier(org.apache.sis.metadata.iso.ImmutableIdentifier) Identifier(org.opengis.metadata.Identifier) WeakValueHashMap(org.apache.sis.util.collection.WeakValueHashMap) HashMap(java.util.HashMap) IdentifiedObject(org.opengis.referencing.IdentifiedObject) SimpleInternationalString(org.apache.sis.util.iso.SimpleInternationalString) ImmutableIdentifier(org.apache.sis.metadata.iso.ImmutableIdentifier)

Aggregations

Identifier (org.opengis.metadata.Identifier)60 ReferenceIdentifier (org.opengis.referencing.ReferenceIdentifier)21 Test (org.junit.Test)14 ImmutableIdentifier (org.apache.sis.metadata.iso.ImmutableIdentifier)11 Citation (org.opengis.metadata.citation.Citation)10 IdentifiedObject (org.opengis.referencing.IdentifiedObject)10 InternationalString (org.opengis.util.InternationalString)10 ArrayList (java.util.ArrayList)8 HashMap (java.util.HashMap)6 DefaultIdentifier (org.apache.sis.metadata.iso.DefaultIdentifier)6 IdentifierMap (org.apache.sis.xml.IdentifierMap)6 GeneralParameterDescriptor (org.opengis.parameter.GeneralParameterDescriptor)5 OperationMethod (org.opengis.referencing.operation.OperationMethod)5 NameToIdentifier (org.apache.sis.internal.metadata.NameToIdentifier)4 NamedIdentifier (org.apache.sis.referencing.NamedIdentifier)4 GenericName (org.opengis.util.GenericName)4 URI (java.net.URI)3 ParameterValueGroup (org.opengis.parameter.ParameterValueGroup)3 IdentityHashMap (java.util.IdentityHashMap)2 LinkedHashMap (java.util.LinkedHashMap)2