Search in sources :

Example 1 with EPSGParameterDomain

use of org.apache.sis.internal.referencing.EPSGParameterDomain in project sis by apache.

the class EPSGDataAccess method createParameterDescriptor.

/**
 * Creates a definition of a single parameter used by an operation method.
 *
 * <div class="note"><b>Example:</b>
 * some EPSG codes for parameters are:
 *
 * <table class="sis" summary="EPSG codes examples">
 *   <tr><th>Code</th> <th>Description</th></tr>
 *   <tr><td>8801</td> <td>Latitude of natural origin</td></tr>
 *   <tr><td>8802</td> <td>Longitude of natural origin</td></tr>
 *   <tr><td>8805</td> <td>Scale factor at natural origin</td></tr>
 *   <tr><td>8806</td> <td>False easting</td></tr>
 *   <tr><td>8807</td> <td>False northing</td></tr>
 * </table></div>
 *
 * @param  code  value allocated by EPSG.
 * @return the parameter descriptor for the given code.
 * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found.
 * @throws FactoryException if the object creation failed for some other reason.
 *
 * @see org.apache.sis.parameter.DefaultParameterDescriptor
 */
@Override
public synchronized ParameterDescriptor<?> createParameterDescriptor(final String code) throws NoSuchAuthorityCodeException, FactoryException {
    ArgumentChecks.ensureNonNull("code", code);
    ParameterDescriptor<?> returnValue = null;
    try (ResultSet result = executeQuery("Coordinate_Operation Parameter", "PARAMETER_CODE", "PARAMETER_NAME", "SELECT PARAMETER_CODE," + " PARAMETER_NAME," + " DESCRIPTION," + " DEPRECATED" + " FROM [Coordinate_Operation Parameter]" + " WHERE PARAMETER_CODE = ?", code)) {
        while (result.next()) {
            final Integer epsg = getInteger(code, result, 1);
            final String name = getString(code, result, 2);
            final String description = getOptionalString(result, 3);
            final boolean deprecated = getOptionalBoolean(result, 4);
            Class<?> type = Double.class;
            /*
                 * If the parameter appears to have at least one non-null value in the "Parameter File Name" column,
                 * then the type is assumed to be URI as a string. Otherwise, the type is a floating point number.
                 */
            try (ResultSet r = executeQuery("ParameterType", "SELECT PARAM_VALUE_FILE_REF FROM [Coordinate_Operation Parameter Value]" + " WHERE (PARAMETER_CODE = ?) AND PARAM_VALUE_FILE_REF IS NOT NULL", epsg)) {
                while (r.next()) {
                    String element = getOptionalString(r, 1);
                    if (element != null && !element.isEmpty()) {
                        type = String.class;
                        break;
                    }
                }
            }
            /*
                 * Search for units.   We typically have many different units but all of the same dimension
                 * (for example metres, kilometres, feet, etc.). In such case, the units Set will have only
                 * one element and that element will be the most frequently used unit.  But some parameters
                 * accept units of different dimensions.   For example the "Ordinate 1 of evaluation point"
                 * (EPSG:8617) parameter value may be in metres or in degrees.   In such case the units Set
                 * will have two elements.
                 */
            final Set<Unit<?>> units = new LinkedHashSet<>();
            try (ResultSet r = executeQuery("ParameterUnit", "SELECT UOM_CODE FROM [Coordinate_Operation Parameter Value]" + " WHERE (PARAMETER_CODE = ?)" + " GROUP BY UOM_CODE" + " ORDER BY COUNT(UOM_CODE) DESC", epsg)) {
                next: while (r.next()) {
                    final String c = getOptionalString(r, 1);
                    if (c != null) {
                        final Unit<?> candidate = owner.createUnit(c);
                        for (final Unit<?> e : units) {
                            if (candidate.isCompatible(e)) {
                                continue next;
                            }
                        }
                        units.add(candidate);
                    }
                }
            }
            /*
                 * Determines if the inverse operation can be performed by reversing the parameter sign.
                 * The EPSG dataset uses "Yes" or "No" value, but SIS scripts use boolean type. We have
                 * to accept both. Note that if we do not recognize the string as a boolean value, then
                 * we need a SQLException, not a null value.  If the value is wrongly null, this method
                 * will succeed anyway and EPSGDataAccess will finish its work without apparent problem,
                 * but Apache SIS will fail later when it will try to compute the inverse operation, for
                 * example in a call to CRS.findOperation(…). The exception thrown at such later time is
                 * much more difficult to relate to the root cause than if we throw the exception here.
                 */
            InternationalString isReversible = null;
            try (ResultSet r = executeQuery("ParameterSign", "SELECT DISTINCT PARAM_SIGN_REVERSAL FROM [Coordinate_Operation Parameter Usage]" + " WHERE (PARAMETER_CODE = ?)", epsg)) {
                if (r.next()) {
                    Boolean b;
                    if (translator.useBoolean()) {
                        b = r.getBoolean(1);
                        if (r.wasNull())
                            b = null;
                    } else {
                        // May throw SQLException - see above comment.
                        b = SQLUtilities.toBoolean(r.getString(1));
                    }
                    if (b != null) {
                        isReversible = b ? SignReversalComment.OPPOSITE : SignReversalComment.SAME;
                    }
                }
            }
            /*
                 * Now creates the parameter descriptor.
                 */
            final NumberRange<?> valueDomain;
            switch(units.size()) {
                case 0:
                    valueDomain = null;
                    break;
                default:
                    valueDomain = new EPSGParameterDomain(units);
                    break;
                case 1:
                    valueDomain = MeasurementRange.create(Double.NEGATIVE_INFINITY, false, Double.POSITIVE_INFINITY, false, CollectionsExt.first(units));
                    break;
            }
            final Map<String, Object> properties = createProperties("Coordinate_Operation Parameter", name, epsg, isReversible, deprecated);
            properties.put(ImmutableIdentifier.DESCRIPTION_KEY, description);
            final ParameterDescriptor<?> descriptor = new DefaultParameterDescriptor<>(properties, 1, 1, type, valueDomain, null, null);
            returnValue = ensureSingleton(descriptor, returnValue, code);
        }
    } catch (SQLException exception) {
        throw databaseFailure(OperationMethod.class, code, exception);
    }
    if (returnValue == null) {
        throw noSuchAuthorityCode(OperationMethod.class, code);
    }
    return returnValue;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) SQLException(java.sql.SQLException) InternationalString(org.opengis.util.InternationalString) SimpleInternationalString(org.apache.sis.util.iso.SimpleInternationalString) Unit(javax.measure.Unit) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) EPSGParameterDomain(org.apache.sis.internal.referencing.EPSGParameterDomain) InternationalString(org.opengis.util.InternationalString) SimpleInternationalString(org.apache.sis.util.iso.SimpleInternationalString) ResultSet(java.sql.ResultSet) AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) IdentifiedObject(org.opengis.referencing.IdentifiedObject) DefaultParameterDescriptor(org.apache.sis.parameter.DefaultParameterDescriptor)

Aggregations

ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 LinkedHashSet (java.util.LinkedHashSet)1 Unit (javax.measure.Unit)1 EPSGParameterDomain (org.apache.sis.internal.referencing.EPSGParameterDomain)1 DefaultParameterDescriptor (org.apache.sis.parameter.DefaultParameterDescriptor)1 AbstractIdentifiedObject (org.apache.sis.referencing.AbstractIdentifiedObject)1 DefaultOperationMethod (org.apache.sis.referencing.operation.DefaultOperationMethod)1 SimpleInternationalString (org.apache.sis.util.iso.SimpleInternationalString)1 IdentifiedObject (org.opengis.referencing.IdentifiedObject)1 InternationalString (org.opengis.util.InternationalString)1