Search in sources :

Example 1 with InvalidParameterValueException

use of org.opengis.parameter.InvalidParameterValueException in project sis by apache.

the class FranceGeocentricInterpolation method createMathTransform.

/**
 * Creates a transform from the specified group of parameter values.
 * This method creates the transform from <em>target</em> to <em>source</em>
 * (which is the direction that use the interpolation grid directly without iteration),
 * then inverts the transform.
 *
 * @param  factory  the factory to use if this constructor needs to create other math transforms.
 * @param  values   the group of parameter values.
 * @return the created math transform.
 * @throws ParameterNotFoundException if a required parameter was not found.
 * @throws FactoryException if an error occurred while loading the grid.
 */
@Override
public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup values) throws ParameterNotFoundException, FactoryException {
    boolean withHeights = false;
    final Parameters pg = Parameters.castOrWrap(values);
    final Integer dim = pg.getValue(Molodensky.DIMENSION);
    if (dim != null)
        switch(dim) {
            case 2:
                break;
            case 3:
                withHeights = true;
                break;
            default:
                throw new InvalidParameterValueException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "dim", dim), "dim", dim);
        }
    final Path file = pg.getMandatoryValue(FILE);
    final DatumShiftGridFile<Angle, Length> grid = getOrLoad(file, isRecognized(file) ? new double[] { TX, TY, TZ } : null, PRECISION);
    MathTransform tr = createGeodeticTransformation(factory, createEllipsoid(pg, Molodensky.TGT_SEMI_MAJOR, Molodensky.TGT_SEMI_MINOR, // GRS 1980 ellipsoid
    CommonCRS.ETRS89.ellipsoid()), createEllipsoid(pg, Molodensky.SRC_SEMI_MAJOR, Molodensky.SRC_SEMI_MINOR, // Clarke 1880 (IGN) ellipsoid
    null), withHeights, grid);
    try {
        tr = tr.inverse();
    } catch (NoninvertibleTransformException e) {
        // Should never happen.
        throw new FactoryException(e);
    }
    return tr;
}
Also used : Path(java.nio.file.Path) NoninvertibleTransformException(org.opengis.referencing.operation.NoninvertibleTransformException) Parameters(org.apache.sis.parameter.Parameters) Angle(javax.measure.quantity.Angle) MathTransform(org.opengis.referencing.operation.MathTransform) InvalidParameterValueException(org.opengis.parameter.InvalidParameterValueException) Length(javax.measure.quantity.Length) FactoryException(org.opengis.util.FactoryException)

Example 2 with InvalidParameterValueException

use of org.opengis.parameter.InvalidParameterValueException in project sis by apache.

the class Verifier method ensureValidValue.

/**
 * Ensures that the given value is valid according the specified parameter descriptor.
 * This method ensures that {@code value} is assignable to the
 * {@linkplain ParameterDescriptor#getValueClass() expected class}, is between the
 * {@linkplain ParameterDescriptor#getMinimumValue() minimum} and
 * {@linkplain ParameterDescriptor#getMaximumValue() maximum} values and is one of the
 * {@linkplain ParameterDescriptor#getValidValues() set of valid values}.
 * If the value fails any of those tests, then an exception is thrown.
 *
 * @param  <T>         the type of parameter value. The given {@code value} should typically be an instance of this class.
 *                     This is not required by this method signature but is checked by this method implementation.
 * @param  descriptor  the parameter descriptor to check against.
 * @param  value       the value to check, or {@code null}.
 * @param  unit        the unit of the value to check, or {@code null}.
 * @return the given value converted to the descriptor unit if any,
 *         then casted to the descriptor parameterized type.
 * @throws InvalidParameterValueException if the parameter value is invalid.
 */
static <T> T ensureValidValue(final ParameterDescriptor<T> descriptor, final Object value, final Unit<?> unit) throws InvalidParameterValueException {
    final Class<T> valueClass = descriptor.getValueClass();
    /*
         * Before to verify if the given value is inside the bounds, we need to convert the value
         * to the units used by the parameter descriptor. The first part of this block verifies
         * the validity of the unit argument, so we execute it even if 'value' is null.
         */
    UnitConverter converter = null;
    Object convertedValue = value;
    if (unit != null) {
        Unit<?> def = descriptor.getUnit();
        if (def == null) {
            def = getCompatibleUnit(Parameters.getValueDomain(descriptor), unit);
            if (def == null) {
                final String name = getDisplayName(descriptor);
                throw new InvalidParameterValueException(Resources.format(Resources.Keys.UnitlessParameter_1, name), name, unit);
            }
        }
        if (!unit.equals(def)) {
            final short expectedID = getUnitMessageID(def);
            if (getUnitMessageID(unit) != expectedID) {
                throw new IllegalArgumentException(Errors.format(expectedID, unit));
            }
            /*
                 * Verify the type of the user's value before to perform the unit conversion,
                 * because the conversion will create a new object not necessarily of the same type.
                 */
            if (value != null) {
                if (!valueClass.isInstance(value)) {
                    final String name = getDisplayName(descriptor);
                    throw new InvalidParameterValueException(Resources.format(Resources.Keys.IllegalParameterValueClass_3, name, valueClass, value.getClass()), name, value);
                }
                /*
                     * From this point we will perform the actual unit conversion. The value may be either
                     * a Number instance, or an array of numbers (typically an array of type double[]). In
                     * the array case, we will store the converted values in a new array of the same type.
                     */
                try {
                    converter = unit.getConverterToAny(def);
                } catch (IncommensurableException e) {
                    throw new IllegalArgumentException(Errors.format(Errors.Keys.IncompatibleUnits_2, unit, def), e);
                }
                Class<?> componentType = valueClass.getComponentType();
                if (componentType == null) {
                    /*
                         * Usual case where the value is not an array. Convert the value directly.
                         * Note that the value can only be a number because the unit is associated
                         * to MeasurementRange, which accepts only numbers.
                         */
                    Number n = converter.convert(((Number) value).doubleValue());
                    try {
                        convertedValue = Numbers.cast(n, valueClass.asSubclass(Number.class));
                    } catch (IllegalArgumentException e) {
                        throw new InvalidParameterValueException(e.getLocalizedMessage(), getDisplayName(descriptor), value);
                    }
                } else {
                    /*
                         * The value is an array. Creates a new array and store the converted values
                         * using Array reflection.
                         */
                    final int length = Array.getLength(value);
                    convertedValue = Array.newInstance(componentType, length);
                    componentType = Numbers.primitiveToWrapper(componentType);
                    for (int i = 0; i < length; i++) {
                        Number n = (Number) Array.get(value, i);
                        // Value in units that we can compare.
                        n = converter.convert(n.doubleValue());
                        try {
                            n = Numbers.cast(n, componentType.asSubclass(Number.class));
                        } catch (IllegalArgumentException e) {
                            throw new InvalidParameterValueException(e.getLocalizedMessage(), getDisplayName(descriptor) + '[' + i + ']', value);
                        }
                        Array.set(convertedValue, i, n);
                    }
                }
            }
        }
    }
    /*
         * At this point the user's value has been fully converted to the unit of measurement specified
         * by the ParameterDescriptor.  Now compare the converted value to the restriction given by the
         * descriptor (set of valid values and range of value domain).
         */
    if (convertedValue != null) {
        final Verifier error;
        final Set<T> validValues = descriptor.getValidValues();
        if (descriptor instanceof DefaultParameterDescriptor<?>) {
            error = ensureValidValue(valueClass, validValues, ((DefaultParameterDescriptor<?>) descriptor).getValueDomain(), convertedValue);
        } else {
            error = ensureValidValue(valueClass, validValues, descriptor.getMinimumValue(), descriptor.getMaximumValue(), convertedValue);
        }
        /*
             * If we found an error, we will usually throw an exception. An exception to this rule is
             * when EPSGDataAccess is creating a deprecated ProjectedCRS in which some parameters are
             * known to be invalid (the CRS was deprecated precisely for that reason). In such cases,
             * we will log a warning instead than throwing an exception.
             */
        if (error != null) {
            error.convertRange(converter);
            final String name = getDisplayName(descriptor);
            final String message = error.message(null, name, value);
            if (!Semaphores.query(Semaphores.SUSPEND_PARAMETER_CHECK)) {
                throw new InvalidParameterValueException(message, name, value);
            } else {
                final LogRecord record = new LogRecord(Level.WARNING, message);
                record.setLoggerName(Loggers.COORDINATE_OPERATION);
                Logging.log(DefaultParameterValue.class, "setValue", record);
            }
        }
    }
    return valueClass.cast(convertedValue);
}
Also used : IncommensurableException(javax.measure.IncommensurableException) InvalidParameterValueException(org.opengis.parameter.InvalidParameterValueException) LogRecord(java.util.logging.LogRecord) UnitConverter(javax.measure.UnitConverter)

Example 3 with InvalidParameterValueException

use of org.opengis.parameter.InvalidParameterValueException in project sis by apache.

the class MathTransformParser method parseParameters.

/**
 * Parses a sequence of {@code "PARAMETER"} elements.
 *
 * @param  element             the parent element containing the parameters to parse.
 * @param  parameters          the group where to store the parameter values.
 * @param  defaultUnit         the default unit (for arbitrary quantity, including angular), or {@code null}.
 * @param  defaultAngularUnit  the default angular unit, or {@code null} if none. This is determined by the context,
 *                             especially when {@link GeodeticObjectParser} parses a {@code ProjectedCRS} element.
 * @throws ParseException if the {@code "PARAMETER"} element can not be parsed.
 */
final void parseParameters(final Element element, final ParameterValueGroup parameters, final Unit<?> defaultUnit, final Unit<Angle> defaultAngularUnit) throws ParseException {
    final Unit<?> defaultSI = (defaultUnit != null) ? defaultUnit.getSystemUnit() : null;
    Element param = element;
    try {
        while ((param = element.pullElement(OPTIONAL, WKTKeywords.Parameter)) != null) {
            final String name = param.pullString("name");
            Unit<?> unit = parseUnit(param);
            param.pullElement(OPTIONAL, ID_KEYWORDS);
            /*
                 * DEPARTURE FROM ISO 19162: the specification recommends that we use the identifier instead
                 * than the parameter name. However we do not yet have a "get parameter by ID" in Apache SIS
                 * or in GeoAPI interfaces. This was not considered necessary since SIS is lenient (hopefully
                 * without introducing ambiguity) regarding parameter names, but we may revisit in a future
                 * version if it become no longer the case. See https://issues.apache.org/jira/browse/SIS-210
                 */
            final ParameterValue<?> parameter = parameters.parameter(name);
            final ParameterDescriptor<?> descriptor = parameter.getDescriptor();
            final Class<?> valueClass = descriptor.getValueClass();
            final boolean isNumeric = Number.class.isAssignableFrom(valueClass);
            if (isNumeric && unit == null) {
                unit = descriptor.getUnit();
                if (unit != null) {
                    final Unit<?> si = unit.getSystemUnit();
                    if (si.equals(defaultSI)) {
                        unit = defaultUnit;
                    } else if (si.equals(Units.RADIAN)) {
                        unit = defaultAngularUnit;
                    }
                }
            }
            if (unit != null) {
                parameter.setValue(param.pullDouble("doubleValue"), unit);
            } else if (isNumeric) {
                if (Numbers.isInteger(valueClass)) {
                    parameter.setValue(param.pullInteger("intValue"));
                } else {
                    parameter.setValue(param.pullDouble("doubleValue"));
                }
            } else if (valueClass == Boolean.class) {
                parameter.setValue(param.pullBoolean("booleanValue"));
            } else {
                parameter.setValue(param.pullString("stringValue"));
            }
            param.close(ignoredElements);
        }
    } catch (ParameterNotFoundException e) {
        throw new UnparsableObjectException(errorLocale, Errors.Keys.UnexpectedParameter_1, new String[] { e.getParameterName() }, param.offset).initCause(e);
    } catch (InvalidParameterValueException e) {
        throw (ParseException) new ParseException(e.getLocalizedMessage(), param.offset).initCause(e);
    }
}
Also used : InvalidParameterValueException(org.opengis.parameter.InvalidParameterValueException) ParseException(java.text.ParseException) ParameterNotFoundException(org.opengis.parameter.ParameterNotFoundException)

Example 4 with InvalidParameterValueException

use of org.opengis.parameter.InvalidParameterValueException in project sis by apache.

the class Molodensky method createMathTransform.

/**
 * Creates a (potentially abridged) Molodensky transform from the specified group of parameter values.
 * The specified number of dimensions are <em>default</em> values; they may be overridden by user parameters.
 *
 * @param  factory           the factory to use for creating concatenated transforms.
 * @param  values            the group of parameter values specified by the users.
 * @param  sourceDimensions  number of source dimensions (2 or 3) of the operation method.
 * @param  targetDimensions  number of target dimensions (2 or 3) of the operation method.
 * @param  isAbridged        {@code true} for the abridged form.
 * @return the created (abridged) Molodensky transform.
 * @throws FactoryException if a transform can not be created.
 */
static MathTransform createMathTransform(final MathTransformFactory factory, final Parameters values, int sourceDimensions, int targetDimensions, final boolean isAbridged) throws FactoryException {
    final Integer dim = values.getValue(DIMENSION);
    if (dim != null) {
        // Unboxing.
        final int n = dim;
        if (n != 2 && n != 3) {
            throw new InvalidParameterValueException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "dim", dim), "dim", dim);
        }
        sourceDimensions = targetDimensions = n;
    }
    /*
         * Following method calls implicitly convert parameter values to metres.
         * We do not try to match ellipsoid axis units because:
         *
         *   1) It complicates the code.
         *   2) We have no guarantees that ellipsoid unit match the coordinate system unit.
         *   3) OGC 01-009 explicitly said that angles are in degrees and heights in metres.
         *   4) The above is consistent with what we do for map projections.
         */
    double sa = values.doubleValue(SRC_SEMI_MAJOR);
    double sb = values.doubleValue(SRC_SEMI_MINOR);
    double ta = optional(values, TGT_SEMI_MAJOR);
    double tb = optional(values, TGT_SEMI_MINOR);
    double Δa = optional(values, AXIS_LENGTH_DIFFERENCE);
    double Δf = optional(values, FLATTENING_DIFFERENCE);
    if (Double.isNaN(ta)) {
        ta = sa + Δa;
    }
    if (Double.isNaN(tb)) {
        tb = ta * (sb / sa - Δf);
    }
    final Map<String, ?> name = Collections.singletonMap(DefaultEllipsoid.NAME_KEY, NilReferencingObject.UNNAMED);
    final Ellipsoid source = new Ellipsoid(name, sa, sb, Δa, Δf);
    final Ellipsoid target = new Ellipsoid(name, ta, tb, -Δa, -Δf);
    source.other = target;
    target.other = source;
    source.computeDifferences(values);
    return MolodenskyTransform.createGeodeticTransformation(factory, source, sourceDimensions >= 3, target, targetDimensions >= 3, values.doubleValue(TX), values.doubleValue(TY), values.doubleValue(TZ), isAbridged);
}
Also used : InvalidParameterValueException(org.opengis.parameter.InvalidParameterValueException) DefaultEllipsoid(org.apache.sis.referencing.datum.DefaultEllipsoid)

Aggregations

InvalidParameterValueException (org.opengis.parameter.InvalidParameterValueException)4 Path (java.nio.file.Path)1 ParseException (java.text.ParseException)1 LogRecord (java.util.logging.LogRecord)1 IncommensurableException (javax.measure.IncommensurableException)1 UnitConverter (javax.measure.UnitConverter)1 Angle (javax.measure.quantity.Angle)1 Length (javax.measure.quantity.Length)1 Parameters (org.apache.sis.parameter.Parameters)1 DefaultEllipsoid (org.apache.sis.referencing.datum.DefaultEllipsoid)1 ParameterNotFoundException (org.opengis.parameter.ParameterNotFoundException)1 MathTransform (org.opengis.referencing.operation.MathTransform)1 NoninvertibleTransformException (org.opengis.referencing.operation.NoninvertibleTransformException)1 FactoryException (org.opengis.util.FactoryException)1