sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1565490 - in /sis/branches/JDK7/core: sis-referencing/src/main/java/org/apache/sis/parameter/ sis-utility/src/main/java/org/apache/sis/util/resources/
Date Thu, 06 Feb 2014 23:53:14 GMT
Author: desruisseaux
Date: Thu Feb  6 23:53:14 2014
New Revision: 1565490

URL: http://svn.apache.org/r1565490
Log:
Initial port of 2 basic map projection parameter classes.
While not really in the scope of SIS 0.4 RC, we need those classes in order
to move GeneralParameterValue WKT formatting code out of the Formatter class.

Added:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterValue.java   (with props)
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java   (with props)
Modified:
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties

Added: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterValue.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterValue.java?rev=1565490&view=auto
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterValue.java (added)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterValue.java [UTF-8] Thu Feb  6 23:53:14 2014
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.parameter;
+
+import java.util.Set;
+import java.io.Serializable;
+import javax.measure.unit.Unit;
+import javax.measure.converter.UnitConverter;
+import javax.measure.converter.ConversionException;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.GeneralParameterValue;
+import org.opengis.parameter.GeneralParameterDescriptor;
+import org.opengis.parameter.InvalidParameterValueException;
+import org.apache.sis.io.wkt.FormattableObject;
+import org.apache.sis.io.wkt.Formatter;
+import org.apache.sis.measure.Units;
+import org.apache.sis.util.Numbers;
+import org.apache.sis.util.resources.Errors;
+
+import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
+
+
+/**
+ * The base class of single parameter value or group of parameter values.
+ *
+ * @author  Martin Desruisseaux (IRD)
+ * @since   0.4 (derived from Geotk-2.0)
+ * @version 0.4
+ * @module
+ */
+public class AbstractParameterValue extends FormattableObject
+        implements GeneralParameterValue, Serializable, Cloneable
+{
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = 8458179223988766398L;
+
+    /**
+     * The abstract definition of this parameter or group of parameters.
+     */
+    final GeneralParameterDescriptor descriptor;
+
+    /**
+     * Creates a parameter value from the specified descriptor.
+     *
+     * @param descriptor The abstract definition of this parameter or group of parameters.
+     */
+    protected AbstractParameterValue(final GeneralParameterDescriptor descriptor) {
+        ensureNonNull("descriptor", descriptor);
+        this.descriptor = descriptor;
+    }
+
+    /**
+     * Creates a new instance initialized with the values from the specified parameter object.
+     * This is a <cite>shallow</cite> copy constructor, since the properties contained in the
+     * given object are not recursively copied.
+     *
+     * @param object The parameter to copy values from, or {@code null} if none.
+     *
+     * @see #castOrCopy(GeneralParameterValue)
+     */
+    protected AbstractParameterValue(final GeneralParameterValue object) {
+        ensureNonNull("object", object);
+        descriptor = object.getDescriptor();
+        if (descriptor == null) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.MissingValueForProperty_1, "descriptor"));
+        }
+    }
+
+    /**
+     * Returns a SIS parameter implementation with the values of the given arbitrary implementation.
+     * This method performs the first applicable actions in the following choices:
+     *
+     * <ul>
+     *   <li>If the given object is {@code null}, then this method returns {@code null}.</li>
+     *   <li>Otherwise if the given object is already an instance of
+     *       {@code AbstractParameterValue}, then it is returned unchanged.</li>
+     *   <li>Otherwise a new {@code AbstractParameterValue} instance is created using the
+     *       {@linkplain #AbstractParameterValue(GeneralParameterValue) copy constructor}
+     *       and returned. Note that this is a <cite>shallow</cite> copy operation, since
+     *       the other properties contained in the given object are not recursively copied.</li>
+     * </ul>
+     *
+     * @param  object The object to get as a SIS implementation, or {@code null} if none.
+     * @return A SIS implementation containing the values of the given object (may be the
+     *         given object itself), or {@code null} if the argument was null.
+     */
+    public static AbstractParameterValue castOrCopy(final GeneralParameterValue object) {
+        if (object == null || object instanceof AbstractParameterValue) {
+            return (AbstractParameterValue) object;
+        }
+        return new AbstractParameterValue(object);
+    }
+
+    /**
+     * Returns the abstract definition of this parameter or group of parameters.
+     *
+     * @return The abstract definition of this parameter or group of parameters.
+     */
+    @Override
+    public GeneralParameterDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    /**
+     * Ensures that the given value is valid according the specified parameter descriptor.
+     * This convenience 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 value casted to the descriptor parameterized type, or the
+     *         {@linkplain ParameterDescriptor#getDefaultValue() default value}
+     *         if the given value was null while the parameter is mandatory.
+     * @throws InvalidParameterValueException if the parameter value is invalid.
+     */
+    @SuppressWarnings("unchecked")
+    static <T> T ensureValidValue(final ParameterDescriptor<T> descriptor, final Object value, final Unit<?> unit)
+            throws InvalidParameterValueException
+    {
+        if (value == null) {
+            if (descriptor.getMinimumOccurs() != 0) {
+                return descriptor.getDefaultValue();
+            }
+            return null;
+        }
+        final String error;
+        /*
+         * Note: the implementation below is similar (except for different error message) to the
+         * one in Parameters.isValidValue(ParameterDescriptor, Object). If one implementation is
+         * modified, the other should be updated accordingly. The main difference is that null
+         * values are replaced by the default value instead than being a conformance error.
+         */
+        final Class<T> type = descriptor.getValueClass();
+        if (!type.isInstance(value)) {
+            error = Errors.format(Errors.Keys.IllegalParameterClass_3, getName(descriptor), type, value.getClass());
+        } else {
+            /*
+             * 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.
+             */
+            T converted = (T) value;
+            if (unit != null) {
+                final Unit<?> def = descriptor.getUnit();
+                if (def == null) {
+                    throw unitlessParameter(descriptor);
+                }
+                if (!unit.equals(def)) {
+                    final short expectedID = getUnitMessageID(def);
+                    if (getUnitMessageID(unit) != expectedID) {
+                        throw new IllegalArgumentException(Errors.format(expectedID, unit));
+                    }
+                    final UnitConverter converter;
+                    try {
+                        converter = unit.getConverterToAny(def);
+                    } catch (ConversionException e) {
+                        throw new IllegalArgumentException(Errors.format(Errors.Keys.IncompatibleUnits_2, unit, def), e);
+                    }
+                    if (Number.class.isAssignableFrom(type)) {
+                        Number n = (Number) value; // Given value.
+                        n = converter.convert(n.doubleValue()); // Value in units that we can compare.
+                        try {
+                            converted = (T) Numbers.cast(n, (Class<? extends Number>) type);
+                        } catch (IllegalArgumentException e) {
+                            throw new InvalidParameterValueException(e.getLocalizedMessage(), getName(descriptor), value);
+                        }
+                    }
+                }
+            }
+            final Comparable<T> minimum = descriptor.getMinimumValue();
+            final Comparable<T> maximum = descriptor.getMaximumValue();
+            if ((minimum != null && minimum.compareTo(converted) > 0) ||
+                (maximum != null && maximum.compareTo(converted) < 0))
+            {
+                error = Errors.format(Errors.Keys.ValueOutOfRange_4, getName(descriptor), minimum, maximum, value);
+            } else {
+                final Set<T> validValues = descriptor.getValidValues();
+                if (validValues!=null && !validValues.contains(value)) {
+                    error = Errors.format(Errors.Keys.IllegalArgumentValue_2, getName(descriptor), value);
+                } else {
+                    /*
+                     * Passed every tests - the value is valid.
+                     * Really returns the original value, not the converted one, because we store the given
+                     * unit as well. Conversions will be applied on the fly by the getter method if needed.
+                     */
+                    return (T) value;
+                }
+            }
+        }
+        throw new InvalidParameterValueException(error, getName(descriptor), value);
+    }
+
+    /**
+     * Returns an exception initialized with a "Unitless parameter" error message for the specified descriptor.
+     */
+    static IllegalStateException unitlessParameter(final GeneralParameterDescriptor descriptor) {
+        return new IllegalStateException(Errors.format(Errors.Keys.UnitlessParameter_1, getName(descriptor)));
+    }
+
+    /**
+     * Convenience method returning the name of the specified descriptor.
+     * This method is used mostly for output to be read by human, not for processing.
+     * Consequently, we may consider to returns a localized name in a future version.
+     */
+    static String getName(final GeneralParameterDescriptor descriptor) {
+        return descriptor.getName().getCode();
+    }
+
+    /**
+     * Returns the unit type as one of error message code.
+     * Used for checking unit with a better error message formatting if needed.
+     */
+    static short getUnitMessageID(final Unit<?> unit) {
+        if (Units.isLinear  (unit)) return Errors.Keys.NonLinearUnit_1;
+        if (Units.isAngular (unit)) return Errors.Keys.NonAngularUnit_1;
+        if (Units.isTemporal(unit)) return Errors.Keys.NonTemporalUnit_1;
+        if (Units.isScale   (unit)) return Errors.Keys.NonScaleUnit_1;
+        return Errors.Keys.IncompatibleUnit_1;
+    }
+
+    /**
+     * Returns a hash value for this parameter.
+     *
+     * @return The hash code value.
+     */
+    @Override
+    public int hashCode() {
+        return descriptor.hashCode() ^ (int) serialVersionUID;
+    }
+
+    /**
+     * Compares the given object with this parameter for equality.
+     *
+     * @param  object The object to compare to {@code this}.
+     * @return {@code true} if both objects are equal.
+     */
+    @Override
+    public boolean equals(final Object object) {
+        if (object != null && object.getClass() == getClass()) {
+            return descriptor.equals(((AbstractParameterValue) object).descriptor);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a copy of this parameter value or group.
+     *
+     * @return A clone of this parameter value or group.
+     */
+    @Override
+    public AbstractParameterValue clone() {
+        try {
+            return (AbstractParameterValue) super.clone();
+        } catch (CloneNotSupportedException exception) {
+            throw new AssertionError(exception); // Should not happen, since we are cloneable
+        }
+    }
+
+    @Override
+    protected String formatTo(final Formatter formatter) {
+        return null;
+    }
+}

Propchange: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterValue.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java?rev=1565490&view=auto
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java (added)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java [UTF-8] Thu Feb  6 23:53:14 2014
@@ -0,0 +1,572 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.parameter;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URI;
+import java.net.URISyntaxException;
+import javax.measure.unit.Unit;
+import javax.measure.converter.UnitConverter;
+import javax.measure.converter.ConversionException;
+import org.opengis.parameter.ParameterValue;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.InvalidParameterTypeException;
+import org.opengis.parameter.InvalidParameterValueException;
+import org.apache.sis.util.resources.Errors;
+
+import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
+
+// Related to JDK7
+import java.util.Objects;
+import java.nio.file.Path;
+
+
+/**
+ * A parameter value used by an operation method. Most CRS parameter values are numeric and can
+ * be obtained by the {@link #intValue()} or {@link #doubleValue()} methods. But other types of
+ * parameter values are possible and can be handled by the more generic {@link #getValue()} and
+ * {@link #setValue(Object)} methods. The type and constraints on parameter values are given by
+ * the {@linkplain #getDescriptor() descriptor}.
+ *
+ * <p>The following table summarizes the ISO attributes with the corresponding getter and setter methods:</p>
+ * <table class="sis">
+ *   <tr><th>ISO attributes</th>   <th>Setter methods</th>                    <th>Getter methods</th></tr>
+ *   <tr><td>booleanValue</td>     <td>{@link #setValue(boolean)}</td>        <td>{@link #booleanValue()}    : {@code boolean}</td></tr>
+ *   <tr><td>integerValue</td>     <td>{@link #setValue(int)}</td>            <td>{@link #intValue()}        : {@code int}</td></tr>
+ *   <tr><td></td>                 <td>{@link #setValue(double)}</td>         <td>{@link #doubleValue()}     : {@code double}</td></tr>
+ *   <tr><td>value</td>            <td>{@link #setValue(double, Unit)}</td>   <td>{@link #doubleValue(Unit)} : {@code double}</td></tr>
+ *   <tr><td>valueList</td>        <td>{@link #setValue(double[], Unit)}</td> <td>{@link #doubleValueList()} : {@code double[]}</td></tr>
+ *   <tr><td></td>                 <td>{@link #setValue(Object)}</td>         <td>{@link #getValue()}        : {@code Object}</td></tr>
+ *   <tr><td>stringValue</td>      <td></td>                                  <td>{@link #stringValue()}     : {@code String}</td></tr>
+ *   <tr><td>integerValueList</td> <td></td>                                  <td>{@link #intValueList()}    : {@code int[]}</td></tr>
+ *   <tr><td>valueFile</td>        <td></td>                                  <td>{@link #valueFile()}       : {@code URI}</td></tr>
+ * </table>
+ *
+ * Instances of {@code ParameterValue} are created by the {@link ParameterDescriptor#createValue()} method.
+ * The parameter type can be fetch with the following idiom:
+ *
+ * {@preformat java
+ *     Class<? extends T> valueClass = parameter.getDescriptor().getValueClass();
+ * }
+ *
+ * {@section Implementation note for subclasses}
+ * All read and write operations (except constructors, {@link #equals(Object)} and {@link #hashCode()})
+ * ultimately delegates to the following methods:
+ *
+ * <ul>
+ *   <li>All getter methods will invoke {@link #getValue()} and - if needed - {@link #getUnit()},
+ *       then perform their processing on the values returned by those methods.</li>
+ *   <li>All setter methods will first convert (if needed) and verify the argument validity,
+ *       then pass the values to the {@link #setValue(Object)} method.</li>
+ * </ul>
+ *
+ * Consequently, the above-cited methods provide single points that subclasses can override
+ * for modifying the behavior of all getter and setter methods.
+ *
+ * @param <T> The value type.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.4 (derived from Geotk-2.0)
+ * @version 0.4
+ * @module
+ *
+ * @see DefaultParameterDescriptor
+ * @see DefaultParameterGroup
+ */
+public class DefaultParameterValue<T> extends AbstractParameterValue implements ParameterValue<T> {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = -5837826787089486776L;
+
+    /**
+     * The value, or {@code null} if undefined.
+     * Except for the constructors, the {@link #equals(Object)} and the {@link #hashCode()} methods,
+     * this field shall be read only by {@link #getValue()} and written by {@link #setValue(Object)}.
+     */
+    private T value;
+
+    /**
+     * The unit of measure for the value, or {@code null} if it doesn't apply.
+     * Except for the constructors, the {@link #equals(Object)} and the {@link #hashCode()} methods,
+     * this field shall be read only by {@link #getUnit()} and written by {@link #setValue(double, Unit)}
+     * or {@link #setValue(double[], Unit)}.
+     */
+    private Unit<?> unit;
+
+    /**
+     * Creates a parameter value from the specified descriptor.
+     * The value will be initialized to the default value, if any.
+     *
+     * @param descriptor The abstract definition of this parameter.
+     */
+    protected DefaultParameterValue(final ParameterDescriptor<T> descriptor) {
+        super(descriptor);
+        value = descriptor.getDefaultValue();
+        unit  = descriptor.getUnit();
+    }
+
+    /**
+     * Returns the abstract definition of this parameter.
+     */
+    @Override
+    @SuppressWarnings("unchecked") // Type checked by the constructor.
+    public ParameterDescriptor<T> getDescriptor() {
+        return (ParameterDescriptor<T>) super.getDescriptor();
+    }
+
+    /**
+     * Returns the unit of measure of the parameter value.
+     * If the parameter value has no unit (for example because it is a {@link String} type),
+     * then this method returns {@code null}. Note that "no unit" does not mean "dimensionless".
+     *
+     * {@section Implementation note for subclasses}
+     * All getter methods which need unit information will invoke this {@code getUnit()} method.
+     * Subclasses can override this method if they need to compute the unit dynamically.
+     *
+     * @return The unit of measure, or {@code null} if none.
+     *
+     * @see #doubleValue()
+     * @see #doubleValueList()
+     * @see #getValue()
+     */
+    @Override
+    public Unit<?> getUnit() {
+        return unit;
+    }
+
+    /**
+     * Returns the parameter value as an object.
+     * If no value has been set, then this method returns the
+     * {@linkplain ParameterDescriptor#getDefaultValue() default value} (which may be null).
+     *
+     * {@section Implementation note for subclasses}
+     * All getter methods will invoke this {@code getValue()} method.
+     * Subclasses can override this method if they need to compute the value dynamically.
+     *
+     * @return The parameter value as an object, or {@code null} if no value has been set
+     *         and there is no default value.
+     *
+     * @see #setValue(Object)
+     */
+    @Override
+    public T getValue() {
+        return value;
+    }
+
+    /**
+     * Returns the boolean value of this parameter.
+     * A boolean value does not have an associated unit of measure.
+     *
+     * @return The boolean value represented by this parameter.
+     * @throws InvalidParameterTypeException if the value is not a boolean type.
+     * @throws IllegalStateException if the value is not defined and there is no default value.
+     *
+     * @see #setValue(boolean)
+     */
+    @Override
+    public boolean booleanValue() throws IllegalStateException {
+        final T value = getValue();
+        if (value instanceof Boolean) {
+            return ((Boolean) value).booleanValue();
+        }
+        throw incompatibleValue(value);
+    }
+
+    /**
+     * Returns the integer value of this parameter, usually used for a count.
+     * An integer value does not have an associated unit of measure.
+     *
+     * @return The numeric value represented by this parameter after conversion to type {@code int}.
+     * @throws InvalidParameterTypeException if the value is not an integer type.
+     * @throws IllegalStateException if the value is not defined and there is no default value.
+     *
+     * @see #setValue(int)
+     * @see #intValueList()
+     */
+    @Override
+    public int intValue() throws IllegalStateException {
+        final T value = getValue();
+        if (value instanceof Number) {
+            final int integer = ((Number) value).intValue();
+            if (integer == ((Number) value).doubleValue()) {
+                return integer;
+            }
+        }
+        throw incompatibleValue(value);
+    }
+
+    /**
+     * Returns an ordered sequence of two or more integer values of this parameter, usually used for counts.
+     * These integer values do not have an associated unit of measure.
+     *
+     * @return The sequence of values represented by this parameter.
+     * @throws InvalidParameterTypeException if the value is not an array of {@code int}s.
+     * @throws IllegalStateException if the value is not defined and there is no default value.
+     *
+     * @see #setValue(Object)
+     * @see #intValue()
+     */
+    @Override
+    public int[] intValueList() throws IllegalStateException {
+        final T value = getValue();
+        if (value instanceof int[]) {
+            return (int[]) value;
+        }
+        throw incompatibleValue(value);
+    }
+
+    /**
+     * Returns the numeric value of this parameter.
+     * The units of measurement are specified by {@link #getUnit()}.
+     *
+     * {@note The behavior of this method is slightly different than the equivalent method in
+     *        the <code>FloatParameter</code> class, since this method throws an exception instead than
+     *        returning <code>NaN</code> if no value has been explicitely set. This method behaves that
+     *        way for consistency will other methods defined in this class, since all of them except
+     *        <code>getValue()</code> throw an exception in such case.}
+     *
+     * @return The numeric value represented by this parameter after conversion to type {@code double}.
+     *         This method returns {@link Double#NaN} only if such "value" has been explicitely set.
+     * @throws InvalidParameterTypeException if the value is not a numeric type.
+     * @throws IllegalStateException if the value is not defined and there is no default value.
+     *
+     * @see #getUnit()
+     * @see #setValue(double)
+     * @see #doubleValueList()
+     */
+    @Override
+    public double doubleValue() throws IllegalStateException {
+        final T value = getValue();
+        if (value instanceof Number) {
+            return ((Number) value).doubleValue();
+        }
+        throw incompatibleValue(value);
+    }
+
+    /**
+     * Returns an ordered sequence of two or more numeric values of this parameter,
+     * where each value has the same associated unit of measure.
+     *
+     * @return The sequence of values represented by this parameter.
+     * @throws InvalidParameterTypeException if the value is not an array of {@code double}s.
+     * @throws IllegalStateException if the value is not defined and there is no default value.
+     *
+     * @see #getUnit()
+     * @see #setValue(Object)
+     * @see #doubleValue()
+     */
+    @Override
+    public double[] doubleValueList() throws IllegalStateException {
+        final T value = getValue();
+        if (value instanceof double[]) {
+            return (double[]) value;
+        }
+        throw incompatibleValue(value);
+    }
+
+    /**
+     * Returns the converter to be used by {@link #doubleValue(Unit)} and {@link #doubleValueList(Unit)}.
+     *
+     * @see #getConverterFrom(Unit)
+     */
+    private UnitConverter getConverterTo(final Unit<?> unit) {
+        final Unit<?> source = getUnit();
+        if (source == null) {
+            throw unitlessParameter(descriptor);
+        }
+        ensureNonNull("unit", unit);
+        final short expectedID = getUnitMessageID(source);
+        if (getUnitMessageID(unit) != expectedID) {
+            throw new IllegalArgumentException(Errors.format(expectedID, unit));
+        }
+        try {
+            return source.getConverterToAny(unit);
+        } catch (ConversionException e) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.IncompatibleUnits_2, source, unit), e);
+        }
+    }
+
+    /**
+     * Returns the numeric value of this parameter in the given unit of measure.
+     * This convenience method applies unit conversions on the fly as needed.
+     *
+     * @param  unit The unit of measure for the value to be returned.
+     * @return The numeric value represented by this parameter after conversion to type
+     *         {@code double} and conversion to {@code unit}.
+     * @throws IllegalArgumentException if the specified unit is invalid for this parameter.
+     * @throws InvalidParameterTypeException if the value is not a numeric type.
+     * @throws IllegalStateException if the value is not defined and there is no default value.
+     *
+     * @see #getUnit()
+     * @see #setValue(double,Unit)
+     * @see #doubleValueList(Unit)
+     */
+    @Override
+    public double doubleValue(final Unit<?> unit) throws IllegalArgumentException, IllegalStateException {
+        return getConverterTo(unit).convert(doubleValue());
+    }
+
+    /**
+     * Returns an ordered sequence of numeric values in the specified unit of measure.
+     * This convenience method applies unit conversions on the fly as needed.
+     *
+     * @param  unit The unit of measure for the value to be returned.
+     * @return The sequence of values represented by this parameter after conversion to type
+     *         {@code double} and conversion to {@code unit}.
+     * @throws IllegalArgumentException if the specified unit is invalid for this parameter.
+     * @throws InvalidParameterTypeException if the value is not an array of {@code double}s.
+     * @throws IllegalStateException if the value is not defined and there is no default value.
+     *
+     * @see #getUnit()
+     * @see #setValue(double[],Unit)
+     * @see #doubleValue(Unit)
+     */
+    @Override
+    public double[] doubleValueList(final Unit<?> unit) throws IllegalArgumentException, IllegalStateException {
+        final UnitConverter converter = getConverterTo(unit);
+        final double[] values = doubleValueList().clone();
+        for (int i=0; i<values.length; i++) {
+            values[i] = converter.convert(values[i]);
+        }
+        return values;
+    }
+
+    /**
+     * Returns the string value of this parameter.
+     * A string value does not have an associated unit of measure.
+     *
+     * @return The string value represented by this parameter.
+     * @throws InvalidParameterTypeException if the value is not a string.
+     * @throws IllegalStateException if the value is not defined and there is no default value.
+     *
+     * @see #getValue()
+     * @see #setValue(Object)
+     */
+    @Override
+    public String stringValue() throws IllegalStateException {
+        final T value = getValue();
+        if (value instanceof CharSequence) {
+            return value.toString();
+        }
+        throw incompatibleValue(value);
+    }
+
+    /**
+     * Returns a reference to a file or a part of a file containing one or more parameter values.
+     * The default implementation can convert the following value types:
+     * {@link URI}, {@link URL}, {@link Path}, {@link File}.
+     *
+     * @return The reference to a file containing parameter values.
+     * @throws InvalidParameterTypeException if the value is not a reference to a file or an URI.
+     * @throws IllegalStateException if the value is not defined and there is no default value.
+     *
+     * @see #getValue()
+     * @see #setValue(Object)
+     */
+    @Override
+    public URI valueFile() throws IllegalStateException {
+        final T value = getValue();
+        if (value instanceof URI) {
+            return (URI) value;
+        }
+        if (value instanceof File) {
+            return ((File) value).toURI();
+        }
+        if (value instanceof Path) {
+            return ((Path) value).toUri();
+        }
+        Exception cause = null;
+        try {
+            if (value instanceof URL) {
+                return ((URL) value).toURI();
+            }
+        } catch (URISyntaxException exception) {
+            cause = exception;
+        }
+        final String name = getName(descriptor);
+        if (value != null) {
+            throw new InvalidParameterTypeException(getClassTypeError(), name);
+        }
+        throw new IllegalStateException(Errors.format(Errors.Keys.MissingValueForParameter_1, cause, name));
+    }
+
+    /**
+     * Returns the exception to throw when an incompatible method is invoked for the value type.
+     */
+    private IllegalStateException incompatibleValue(final Object value) {
+        final String name = getName(descriptor);
+        if (value != null) {
+            return new InvalidParameterTypeException(getClassTypeError(), name);
+        }
+        return new IllegalStateException(Errors.format(Errors.Keys.MissingValueForParameter_1, name));
+    }
+
+    /**
+     * Formats an error message for illegal method call for the current value type.
+     */
+    private String getClassTypeError() {
+        return Errors.format(Errors.Keys.IllegalOperationForValueClass_1,
+                ((ParameterDescriptor<?>) descriptor).getValueClass());
+    }
+
+    /**
+     * Sets the parameter value as an object. The object type is typically a {@link Double}, {@link Integer},
+     * {@link Boolean}, {@link String}, {@link URI}, {@code double[]} or {@code int[]}.
+     *
+     * @param  value The parameter value, or {@code null} to restore the default value.
+     * @throws InvalidParameterValueException if the type of {@code value} is inappropriate for this parameter,
+     *         or if the value is illegal for some other reason (for example the value is numeric and out of range).
+     *
+     * @see #getValue()
+     */
+    @Override
+    @SuppressWarnings("unchecked") // Safe because type was checked by the constructor.
+    public void setValue(final Object value) throws InvalidParameterValueException {
+        this.value = ensureValidValue((ParameterDescriptor<T>) descriptor, value, unit);
+    }
+
+    /**
+     * Sets the parameter value as a boolean.
+     *
+     * @param  value The parameter value.
+     * @throws InvalidParameterValueException if the boolean type is inappropriate for this parameter.
+     *
+     * @see #booleanValue()
+     */
+    @Override
+    public void setValue(final boolean value) throws InvalidParameterValueException {
+        setValue((Object) Boolean.valueOf(value));
+    }
+
+    /**
+     * Sets the parameter value as an integer.
+     *
+     * @param  value The parameter value.
+     * @throws InvalidParameterValueException if the integer type is inappropriate for this parameter,
+     *         or if the value is illegal for some other reason (for example a value out of range).
+     *
+     * @see #intValue()
+     */
+    @Override
+    public void setValue(final int value) throws InvalidParameterValueException {
+        setValue(value);
+    }
+
+    /**
+     * Sets the parameter value as a floating point. The unit, if any, stay unchanged.
+     *
+     * @param value The parameter value.
+     * @throws InvalidParameterValueException if the floating point type is inappropriate for this
+     *         parameter, or if the value is illegal for some other reason (for example a value out
+     *         of range).
+     *
+     * @see #setValue(double,Unit)
+     * @see #doubleValue()
+     */
+    @Override
+    public void setValue(final double value) throws InvalidParameterValueException {
+        setValue(value);
+    }
+
+    /**
+     * Sets the parameter value as a floating point and its associated unit.
+     *
+     * @param  value The parameter value.
+     * @param  unit The unit for the specified value.
+     * @throws InvalidParameterValueException if the floating point type is inappropriate for this parameter,
+     *         or if the value is illegal for some other reason (for example a value out of range).
+     *
+     * @see #setValue(double)
+     * @see #doubleValue(Unit)
+     */
+    @Override
+    public void setValue(final double value, final Unit<?> unit) throws InvalidParameterValueException {
+        final Unit<?> old = this.unit;
+        this.unit = unit;
+        try {
+            setValue(value);
+        } catch (InvalidParameterValueException e) {
+            this.unit = old;
+            throw e;
+        }
+    }
+
+    /**
+     * Sets the parameter value as an array of floating point and their associated unit.
+     *
+     * @param  values The parameter values.
+     * @param  unit The unit for the specified value.
+     * @throws InvalidParameterValueException if the floating point array type is inappropriate for this parameter,
+     *         or if the value is illegal for some other reason (for example a value out of range).
+     */
+    @Override
+    public void setValue(final double[] values, final Unit<?> unit) throws InvalidParameterValueException {
+        final Unit<?> old = this.unit;
+        this.unit = unit;
+        try {
+            setValue(value);
+        } catch (InvalidParameterValueException e) {
+            this.unit = old;
+            throw e;
+        }
+    }
+
+    /**
+     * Compares the specified object with this parameter for equality.
+     *
+     * @param  object The object to compare to {@code this}.
+     * @return {@code true} if both objects are equal.
+     */
+    @Override
+    public boolean equals(final Object object) {
+        if (object == this) {
+            // Slight optimization
+            return true;
+        }
+        if (super.equals(object)) {
+            final DefaultParameterValue<?> that = (DefaultParameterValue<?>) object;
+            return Objects.equals(this.value, that.value) &&
+                   Objects.equals(this.unit,  that.unit);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash value for this parameter.
+     *
+     * @return The hash code value. This value doesn't need to be the same
+     *         in past or future versions of this class.
+     */
+    @Override
+    public int hashCode() {
+        int code = 37 * super.hashCode();
+        if (value != null) code +=   value.hashCode();
+        if (unit  != null) code += 31*unit.hashCode();
+        return code;
+    }
+
+    /**
+     * Returns a clone of this parameter value.
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public DefaultParameterValue<T> clone() {
+        return (DefaultParameterValue<T>) super.clone();
+    }
+}

Propchange: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1565490&r1=1565489&r2=1565490&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Thu Feb  6 23:53:14 2014
@@ -256,6 +256,11 @@ public final class Errors extends Indexe
         public static final short IllegalMemberType_2 = 37;
 
         /**
+         * This operation can not be applied to values of class ‘{0}’.
+         */
+        public static final short IllegalOperationForValueClass_1 = 141;
+
+        /**
          * Option ‘{0}’ can not take the “{1}” value.
          */
         public static final short IllegalOptionValue_2 = 38;
@@ -266,7 +271,13 @@ public final class Errors extends Indexe
         public static final short IllegalOrdinateRange_3 = 39;
 
         /**
-         * Property ‘{0}’ does not accept instances of ‘{1}’.
+         * Parameter “{0}” does not accept instances of ‘{2}’. Expected an instance of ‘{1}’ or derived
+         * type.
+         */
+        public static final short IllegalParameterClass_3 = 138;
+
+        /**
+         * Property “{0}” does not accept instances of ‘{1}’.
          */
         public static final short IllegalPropertyClass_2 = 40;
 
@@ -296,6 +307,11 @@ public final class Errors extends Indexe
         public static final short IncompatiblePropertyValue_1 = 45;
 
         /**
+         * Unit “{0}” is incompatible with current value.
+         */
+        public static final short IncompatibleUnit_1 = 140;
+
+        /**
          * Units “{0}” and “{1}” are incompatible.
          */
         public static final short IncompatibleUnits_2 = 46;
@@ -391,6 +407,11 @@ public final class Errors extends Indexe
         public static final short MissingValueForOption_1 = 63;
 
         /**
+         * Missing value for parameter “{0}”.
+         */
+        public static final short MissingValueForParameter_1 = 142;
+
+        /**
          * Missing value for property “{0}”.
          */
         public static final short MissingValueForProperty_1 = 64;
@@ -641,6 +662,11 @@ public final class Errors extends Indexe
         public static final short UnexpectedFileFormat_2 = 111;
 
         /**
+         * Parameter “{0}” has no unit.
+         */
+        public static final short UnitlessParameter_1 = 139;
+
+        /**
          * Authority “{0}” is unknown.
          */
         public static final short UnknownAuthority_1 = 136;

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1565490&r1=1565489&r2=1565490&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Thu Feb  6 23:53:14 2014
@@ -56,19 +56,22 @@ IllegalArgumentClass_3            = Argu
 IllegalArgumentField_4            = Argument \u2018{0}\u2019 can not take the \u201c{1}\u201d value, because the \u2018{2}\u2019 field can not take the \u201c{3}\u201d value.
 IllegalArgumentValue_2            = Argument \u2018{0}\u2019 can not take the \u201c{1}\u201d value.
 IllegalAxisDirection_2            = Coordinate system of class \u2018{0}\u2019 can not have axis in the {1} direction.
-IllegalOptionValue_2              = Option \u2018{0}\u2019 can not take the \u201c{1}\u201d value.
 IllegalBitsPattern_1              = Illegal bits pattern: {0}.
 IllegalClass_2                    = Class \u2018{1}\u2019 is illegal. It must be \u2018{0}\u2019 or a derived class.
 IllegalFormatPatternForClass_2    = The \u201c{1}\u201d pattern can not be applied to formating of objects of type \u2018{0}\u2019.
 IllegalLanguageCode_1             = The \u201c{0}\u201d language is not recognized.
 IllegalMemberType_2               = Member \u201c{0}\u201d can not be associated to type \u201c{1}\u201d.
+IllegalOperationForValueClass_1   = This operation can not be applied to values of class \u2018{0}\u2019.
+IllegalOptionValue_2              = Option \u2018{0}\u2019 can not take the \u201c{1}\u201d value.
 IllegalOrdinateRange_3            = The [{0} \u2026 {1}] range of ordinate values is not valid for the \u201c{2}\u201d axis.
-IllegalPropertyClass_2            = Property \u2018{0}\u2019 does not accept instances of \u2018{1}\u2019.
+IllegalParameterClass_3           = Parameter \u201c{0}\u201d does not accept instances of \u2018{2}\u2019. Expected an instance of \u2018{1}\u2019 or derived type.
+IllegalPropertyClass_2            = Property \u201c{0}\u201d does not accept instances of \u2018{1}\u2019.
 IllegalRange_2                    = Range [{0} \u2026 {1}] is not valid.
 IllegalUnicodeCodePoint_2         = Value {1} for \u201c{0}\u201d is not a valid Unicode code point.
 IllegalUnitFor_2                  = Unit of measurement \u201c{1}\u201d is not valid for \u201c{0}\u201d values.
 IncompatibleCoordinateSystemTypes = Incompatible coordinate system types.
 IncompatiblePropertyValue_1       = Property \u201c{0}\u201d has an incompatible value.
+IncompatibleUnit_1                = Unit \u201c{0}\u201d is incompatible with current value.
 IncompatibleUnits_2               = Units \u201c{0}\u201d and \u201c{1}\u201d are incompatible.
 InconsistentAttribute_2           = Value \u201c{1}\u201d of attribute \u2018{0}\u2019 is inconsistent with other attributes.
 InconsistentTableColumns          = Inconsistent table columns.
@@ -89,6 +92,7 @@ MissingAuthority_1                = No a
 MissingRequiredModule_1           = This operation requires the \u201c{0}\u201d module.
 MissingSchemeInURI                = Missing scheme in URI.
 MissingValueForOption_1           = Missing value for option \u201c{0}\u201d.
+MissingValueForParameter_1        = Missing value for parameter \u201c{0}\u201d.
 MissingValueForProperty_1         = Missing value for property \u201c{0}\u201d.
 MissingValueInColumn_1            = Missing value in the \u201c{0}\u201d column.
 MutuallyExclusiveOptions_2        = Options \u201c{0}\u201d and \u201c{1}\u201d are mutually exclusive.
@@ -140,6 +144,7 @@ UnexpectedChange_1                = Unex
 UnexpectedEndOfFile_1             = Unexpected end of file while reading \u201c{0}\u201d.
 UnexpectedEndOfString_1           = More characters were expected at the end of \u201c{0}\u201d.
 UnexpectedFileFormat_2            = File \u201c{1}\u201d seems to be encoded in an other format than {0}.
+UnitlessParameter_1               = Parameter \u201c{0}\u201d has no unit.
 UnknownAuthority_1                = Authority \u201c{0}\u201d is unknown.
 UnknownAxisDirection_1            = Axis direction \u201c{0}\u201d is unknown.
 UnknownCommand_1                  = Command \u201c{0}\u201d is not recognized.

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1565490&r1=1565489&r2=1565490&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Thu Feb  6 23:53:14 2014
@@ -46,19 +46,22 @@ IllegalArgumentClass_3            = L\u2
 IllegalArgumentField_4            = L\u2019argument \u2018{0}\u2019 n\u2019accepte pas la valeur \u00ab\u202f{1}\u202f\u00bb parce que le champs \u2018{2}\u2019 ne peut pas prendre la valeur \u00ab\u202f{3}\u202f\u00bb.
 IllegalArgumentValue_2            = L\u2019argument \u2018{0}\u2019 n\u2019accepte pas la valeur \u00ab\u202f{1}\u202f\u00bb.
 IllegalAxisDirection_2            = Les syst\u00e8mes de coordonn\u00e9es de classe \u2018{0}\u2019 ne peuvent pas avoir d\u2019axe dans la direction \u00ab\u202f{1}\u202f\u00bb.
-IllegalOptionValue_2              = L\u2019option \u2018{0}\u2019 n\u2019accepte pas la valeur \u00ab\u202f{1}\u202f\u00bb.
 IllegalBitsPattern_1              = Pattern de bits invalide: {0}.
 IllegalClass_2                    = La classe \u2018{1}\u2019 est ill\u00e9gale. Il doit s\u2019agir d\u2019une classe \u2018{0}\u2019 ou d\u00e9riv\u00e9e.
 IllegalFormatPatternForClass_2    = Le mod\u00e8le \u00ab\u202f{1}\u202f\u00bb ne peut pas \u00eatre appliqu\u00e9 au formatage d\u2019objets de type \u2018{0}\u2019.
 IllegalLanguageCode_1             = Le code de langue \u00ab\u202f{0}\u202f\u00bb n\u2019est pas reconnu.
 IllegalMemberType_2               = Le membre \u00ab\u202f{0}\u202f\u00bb ne peut pas \u00eatre associ\u00e9 au type \u00ab\u202f{1}\u202f\u00bb.
+IllegalOperationForValueClass_1   = Cette op\u00e9ration ne peut pas s\u2019appliquer aux valeurs de classe \u2018{0}\u2019.
+IllegalOptionValue_2              = L\u2019option \u2018{0}\u2019 n\u2019accepte pas la valeur \u00ab\u202f{1}\u202f\u00bb.
 IllegalOrdinateRange_3            = La plage de valeurs de coordonn\u00e9es [{0} \u2026 {1}] n\u2019est pas valide pour l\u2019axe \u00ab\u202f{2}\u202f\u00bb.
-IllegalPropertyClass_2            = La propri\u00e9t\u00e9 \u2018{0}\u2019 n\u2019accepte pas les valeurs de type \u2018{1}\u2019.
+IllegalParameterClass_3           = Le param\u00e8tre \u00ab\u202f{0}\u202f\u00bb n\u2019accepte pas les valeurs de type \u2018{2}\u2019. Une instance de \u2018{1}\u2019 ou d\u2019un type d\u00e9riv\u00e9 \u00e9tait attendue.
+IllegalPropertyClass_2            = La propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019accepte pas les valeurs de type \u2018{1}\u2019.
 IllegalRange_2                    = La plage [{0} \u2026 {1}] n\u2019est pas valide.
 IllegalUnicodeCodePoint_2         = La valeur {1} de \u00ab\u202f{0}\u202f\u00bb n\u2019est pas un code Unicode valide.
 IllegalUnitFor_2                  = L\u2019unit\u00e9 de mesure \u00ab\u202f{1}\u202f\u00bb n\u2019est pas valide pour les valeurs de \u00ab\u202f{0}\u202f\u00bb.
 IncompatibleCoordinateSystemTypes = Types de syst\u00e8mes de coordonn\u00e9es incompatibles.
 IncompatiblePropertyValue_1       = La valeur de la propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019est pas compatible.
+IncompatibleUnit_1                = L\u2019unit\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019est pas compatible avec la valeur actuelle.
 IncompatibleUnits_2               = Les unit\u00e9s \u00ab\u202f{0}\u202f\u00bb et \u00ab\u202f{1}\u202f\u00bb ne sont pas compatibles.
 InconsistentAttribute_2           = La valeur \u00ab\u202f{1}\u202f\u00bb de l\u2019attribut \u2018{0}\u2019 n\u2019est pas coh\u00e9rente avec celles des autres attributs.
 InconsistentTableColumns          = Les colonnes des tables ne sont pas coh\u00e9rentes.
@@ -79,6 +82,7 @@ MissingAuthority_1                = Aucu
 MissingRequiredModule_1           = Cette op\u00e9ration requiert le module \u00ab\u202f{0}\u202f\u00bb.
 MissingSchemeInURI                = Il manque le sch\u00e9ma d\u2019URI.
 MissingValueForOption_1           = Aucune valeur n\u2019a \u00e9t\u00e9 d\u00e9finie pour l\u2019option \u00ab\u202f{0}\u202f\u00bb.
+MissingValueForParameter_1        = Aucune valeur n\u2019a \u00e9t\u00e9 d\u00e9finie pour le param\u00e8tre \u00ab\u202f{0}\u202f\u00bb.
 MissingValueForProperty_1         = Aucune valeur n\u2019a \u00e9t\u00e9 d\u00e9finie pour la propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb.
 MissingValueInColumn_1            = Il manque une valeur dans la colonne \u00ab\u202f{0}\u202f\u00bb.
 MutuallyExclusiveOptions_2        = Les options \u00ab\u202f{0}\u202f\u00bb et \u00ab\u202f{1}\u202f\u00bb sont mutuellement exclusives.
@@ -129,6 +133,7 @@ UnexpectedChange_1                = Chan
 UnexpectedEndOfFile_1             = Fin de fichier inattendue lors de la lecture de \u00ab\u202f{0}\u202f\u00bb.
 UnexpectedEndOfString_1           = D\u2019autres caract\u00e8res \u00e9taient attendus \u00e0 la fin du texte \u00ab\u202f{0}\u202f\u00bb.
 UnexpectedFileFormat_2            = Le fichier \u00ab\u202f{1}\u202f\u00bb semble \u00eatre encod\u00e9 dans un autre format que {0}.
+UnitlessParameter_1               = Le param\u00e8tre \u201c{0}\u201d n\u2019a pas d\u2019unit\u00e9.
 UnknownAuthority_1                = L\u2019autorit\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019est pas reconnue.
 UnknownAxisDirection_1            = La direction d\u2019axe \u00ab\u202f{0}\u202f\u00bb n\u2019est pas reconnue.
 UnknownCommand_1                  = La commande \u00ab\u202f{0}\u202f\u00bb n\u2019est pas reconnue.



Mime
View raw message