sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1696513 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/ sis-referencing/src/main/java/org/apache/sis/parameter/ sis-referencing/src/main/java/org/apache/sis/referencing/ sis-referencing...
Date Wed, 19 Aug 2015 02:35:11 GMT
Author: desruisseaux
Date: Wed Aug 19 02:35:11 2015
New Revision: 1696513

URL: http://svn.apache.org/r1696513
Log:
Complete the <gml:ParameterValue> support with the (un)marshalling of the <gml:OperationParameter> element.
This is a little bit tricky since the DefaultParameterDescriptor.valueClass property is mandatory in SIS but
not part of GML, so we have to infer it from the enclosing <gml:ParameterValue>. Since <gml:OperationParameter>
may not be always enclosed in a <gml:ParameterValue> element, we also make the code a little bit more robust to
null descriptor and null valueClass, even if such objects should be invalid from SIS perspective.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameter.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterDescriptor.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Verifier.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/package-info.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterMarshallingTest.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/PropertyType.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/NumberRange.java

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameter.java?rev=1696513&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameter.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameter.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -0,0 +1,158 @@
+/*
+ * 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.internal.jaxb.referencing;
+
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlElement;
+import javax.measure.unit.Unit;
+import javax.measure.unit.SI;
+import javax.measure.unit.NonSI;
+import org.opengis.parameter.ParameterValue;
+import org.opengis.parameter.ParameterDescriptor;
+import org.apache.sis.internal.jaxb.Context;
+import org.apache.sis.internal.jaxb.gco.PropertyType;
+import org.apache.sis.measure.MeasurementRange;
+import org.apache.sis.parameter.DefaultParameterDescriptor;
+
+
+/**
+ * JAXB adapter mapping implementing class to the GeoAPI interface. See
+ * package documentation for more information about JAXB and interface.
+ *
+ * <p>This class tries also to resolve another difficulty: our implementation class needs to know
+ * the base class of values, but this information is not provided in the XML documents. We have to
+ * infer it from the actual value.</p>
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.6
+ * @version 0.6
+ * @module
+ */
+public final class CC_OperationParameter extends PropertyType<CC_OperationParameter, ParameterDescriptor<?>> {
+    /**
+     * The class of the value of the enclosing {@code <gml:ParameterValue>} element, or {@code null} if unknown.
+     *
+     * <p>This is set by the private {@code beforeMarshal(…)} method at unmarshalling time
+     * and read by the {@link DefaultParameterDescriptor} default constructor.</p>
+     */
+    public Class<?> valueClass;
+
+    /**
+     * The domain of values of the enclosing {@code <gml:ParameterValue>} element, or {@code null} if unknown.
+     * If non-null, typically only the unit of measurement is relevant in this object.
+     *
+     * <p>This is set by the private {@code beforeUnmarshal(…)} method at unmarshalling time
+     * and read by the {@link DefaultParameterDescriptor} default constructor.</p>
+     */
+    public MeasurementRange<?> valueDomain;
+
+    /**
+     * Empty constructor for JAXB only.
+     */
+    public CC_OperationParameter() {
+    }
+
+    /**
+     * Returns the GeoAPI interface which is bound by this adapter.
+     * This method is indirectly invoked by the private constructor
+     * below, so it shall not depend on the state of this object.
+     *
+     * @return {@code ParameterDescriptor.class}
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    protected Class<ParameterDescriptor<?>> getBoundType() {
+        return (Class) ParameterDescriptor.class;
+    }
+
+    /**
+     * Constructor for the {@link #wrap} method only.
+     */
+    private CC_OperationParameter(final ParameterDescriptor<?> parameter) {
+        super(parameter);
+    }
+
+    /**
+     * Invoked by {@link PropertyType} at marshalling time for wrapping the given value
+     * in a {@code <gml:OperationParameter>} XML element.
+     *
+     * @param  parameter The element to marshall.
+     * @return A {@code PropertyType} wrapping the given the element.
+     */
+    @Override
+    protected CC_OperationParameter wrap(final ParameterDescriptor<?> parameter) {
+        return new CC_OperationParameter(parameter);
+    }
+
+    /**
+     * Invoked by JAXB at marshalling time for getting the actual element to write
+     * inside the {@code <gml:OperationParameter>} XML element.
+     * This is the value or a copy of the value given in argument to the {@code wrap} method.
+     *
+     * @return The element to be marshalled.
+     */
+    @XmlElement(name = "OperationParameter")
+    public DefaultParameterDescriptor<?> getElement() {
+        return DefaultParameterDescriptor.castOrCopy(metadata);
+    }
+
+    /**
+     * Invoked by JAXB at unmarshalling time for storing the result temporarily.
+     *
+     * @param parameter The unmarshalled element.
+     */
+    public void setElement(final DefaultParameterDescriptor<?> parameter) {
+        metadata = parameter;
+    }
+
+    /**
+     * Invoked by JAXB during unmarshalling of the enclosing {@code <gml:OperationParameter>},
+     * before the child {@link DefaultParameterDescriptor}. This method stores the class and
+     * the unit of measurement of the parameter descriptor to create. Those information will
+     * be used by the {@link DefaultParameterDescriptor} private constructor.
+     *
+     * @param unmarshaller The unmarshaller.
+     * @param parent The enclosing {@link ParameterValue} instance being unmarshalled.
+     */
+    private void beforeUnmarshal(final Unmarshaller unmarshaller, final Object parent) {
+        if (parent instanceof ParameterValue<?>) {
+            final Object value = ((ParameterValue<?>) parent).getValue();
+            if (value != null) {
+                valueClass = value.getClass();
+                Unit<?> unit = ((ParameterValue<?>) parent).getUnit();
+                if (unit != null) {
+                    unit = unit.toSI();
+                    if (SI.RADIAN.equals(unit)) {
+                        unit = NonSI.DEGREE_ANGLE;
+                    }
+                    assert (valueClass == Double.class) || (valueClass == double[].class) : valueClass;
+                    valueDomain = MeasurementRange.create(Double.NEGATIVE_INFINITY, false,
+                                                          Double.POSITIVE_INFINITY, false, unit);
+                }
+                Context.setWrapper(Context.current(), this);
+            }
+        }
+    }
+
+    /**
+     * Clears the value class and units of measurement after {@code <gml:OperationParameter>} unmarshalling
+     * for avoiding that those information are wrongly used for an unrelated {@link ParameterDescriptor}.
+     */
+    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
+        Context.setWrapper(Context.current(), null);
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterDescriptor.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterDescriptor.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterDescriptor.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/AbstractParameterDescriptor.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -17,7 +17,10 @@
 package org.apache.sis.parameter;
 
 import java.util.Map;
-import org.opengis.util.InternationalString;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlSchemaType;
 import org.opengis.parameter.ParameterDirection;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
@@ -91,9 +94,16 @@ import java.util.Objects;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.5
+ * @version 0.6
  * @module
  */
+@XmlType(name = "AbstractGeneralOperationParameterType", propOrder = {
+    "nonDefaultMinimumOccurs",
+    "nonDefaultMaximumOccurs"
+})
+@XmlSeeAlso({
+    DefaultParameterDescriptor.class
+})
 public abstract class AbstractParameterDescriptor extends AbstractIdentifiedObject implements GeneralParameterDescriptor {
     /**
      * Serial number for inter-operability with different versions.
@@ -104,8 +114,11 @@ public abstract class AbstractParameterD
      * The minimum number of times that values for this parameter group are required, as an unsigned short.
      * We use a short because this value is usually either 0 or 1, or a very small number like 2 or 3.
      * A large number would be a bad idea with this parameter implementation.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link #setNonDefaultMinimumOccurs(Integer)}</p>
      */
-    private final short minimumOccurs;
+    private short minimumOccurs;
 
     /**
      * The maximum number of times that values for this parameter group are required, as an unsigned short.
@@ -113,8 +126,22 @@ public abstract class AbstractParameterD
      *
      * <p>We use a short because this value is usually 1 or a very small number like 2 or 3. This also serve
      * as a safety since a large number would be a bad idea with this parameter implementation.</p>
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link #setNonDefaultMaximumOccurs(Integer)}</p>
+     */
+    private short maximumOccurs;
+
+    /**
+     * Constructs a new object in which every attributes are set to a null value.
+     * <strong>This is not a valid object.</strong> This constructor is strictly
+     * reserved to JAXB, which will assign values to the fields using reflexion.
      */
-    private final short maximumOccurs;
+    AbstractParameterDescriptor() {
+        super(org.apache.sis.internal.referencing.NilReferencingObject.INSTANCE);
+        minimumOccurs = 1;  // Default value is XML element is omitted.
+        maximumOccurs = 1;
+    }
 
     /**
      * Constructs a parameter descriptor from a set of properties. The properties map is given unchanged to the
@@ -218,18 +245,6 @@ public abstract class AbstractParameterD
     }
 
     /**
-     * Returns a narrative explanation of the role of the parameter. The default implementation returns
-     * the {@linkplain org.apache.sis.metadata.iso.ImmutableIdentifier#getDescription() description}
-     * provided by the parameter {@linkplain #getName() name}.
-     *
-     * @return A narrative explanation of the role of the parameter, or {@code null} if none.
-     */
-    @Override
-    public InternationalString getDescription() {
-        return getName().getDescription();
-    }
-
-    /**
      * The minimum number of times that values for this parameter group or parameter are required.
      * A value of 0 means an optional parameter.
      *
@@ -347,4 +362,48 @@ public abstract class AbstractParameterD
         }
         return WKTKeywords.Parameter;
     }
+
+    // ---- XML SUPPORT ----------------------------------------------------
+
+    /**
+     * Invoked by JAXB for marshalling the {@link #minimumOccurs} value. Omit marshalling of this
+     * {@code gml:minimumOccurs} element if its value is equals to the default value, which is 1.
+     */
+    @XmlElement(name = "minimumOccurs")
+    @XmlSchemaType(name = "nonNegativeInteger")
+    private Integer getNonDefaultMinimumOccurs() {
+        final int n = getMinimumOccurs();
+        return (n != 1) ? n : null;
+    }
+
+    /**
+     * Invoked by JAXB for marshalling the {@link #maximumOccurs} value. Omit marshalling of this
+     * {@code gml:maximumOccurs} element if its value is equals to the default value, which is 1.
+     *
+     * <p>This property should not be marshalled in {@link DefaultParameterDescriptor} objects (the GML schema
+     * does not allow that). It should be marshalled only for {@link DefaultParameterDescriptorGroup} objects.
+     * Since SIS marshals {@code minimumOccurs} and {@code maximumOccurs} properties only when their value is
+     * different than 1, and since {@code ParameterDescriptor} should not have a {@code maximumOccurs} value
+     * different than 1 when ISO 19111 compliance is desired, the GML document should be valid in most cases.</p>
+     */
+    @XmlElement(name = "maximumOccurs")
+    @XmlSchemaType(name = "nonNegativeInteger")
+    private Integer getNonDefaultMaximumOccurs() {
+        final int n = getMaximumOccurs();
+        return (n != 1) ? n : null;
+    }
+
+    /**
+     * Invoked by JAXB for unmarshalling the {@link #minimumOccurs} value.
+     */
+    private void setNonDefaultMinimumOccurs(final Integer n) {
+        minimumOccurs = (n != null) ? crop(n) : 1;
+    }
+
+    /**
+     * Invoked by JAXB for unmarshalling the {@link #maximumOccurs} value.
+     */
+    private void setNonDefaultMaximumOccurs(final Integer n) {
+        maximumOccurs = (n != null) ? crop(n) : 1;
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -19,6 +19,8 @@ package org.apache.sis.parameter;
 import java.util.Arrays;
 import java.util.Set;
 import java.util.Map;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlRootElement;
 import javax.measure.unit.Unit;
 import org.opengis.util.CodeList;
 import org.opengis.parameter.ParameterValue;
@@ -31,6 +33,9 @@ import org.apache.sis.measure.Range;
 import org.apache.sis.measure.MeasurementRange;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.internal.jaxb.Context;
+import org.apache.sis.internal.jaxb.gco.PropertyType;
+import org.apache.sis.internal.jaxb.referencing.CC_OperationParameter;
 import org.apache.sis.referencing.IdentifiedObjects;
 
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
@@ -64,12 +69,14 @@ import java.util.Objects;
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Johann Sorel (Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.6
  * @module
  *
  * @see DefaultParameterValue
  * @see DefaultParameterDescriptorGroup
  */
+@XmlType(name = "OperationParameterType")
+@XmlRootElement(name = "OperationParameter")
 public class DefaultParameterDescriptor<T> extends AbstractParameterDescriptor implements ParameterDescriptor<T> {
     /**
      * Serial number for inter-operability with different versions.
@@ -85,7 +92,7 @@ public class DefaultParameterDescriptor<
 
     /**
      * A set of valid values (usually from a {@linkplain CodeList code list})
-     * or {@code null} if it doesn't apply. This set is immutable.
+     * or {@code null} if it does not apply. This set is immutable.
      *
      * @see #getValidValues()
      */
@@ -114,6 +121,37 @@ public class DefaultParameterDescriptor<
     private final T defaultValue;
 
     /**
+     * Constructs a new object in which every attributes are set to a null value.
+     * <strong>This is not a valid object.</strong> This constructor is strictly
+     * reserved to JAXB, which will assign values to the fields using reflexion.
+     *
+     * <p>This constructor fetches the value class and the unit of measurement from the enclosing
+     * {@link DefaultParameterValue}, if presents, because those information are not presents in GML.
+     * They are GeoAPI additions.</p>
+     */
+    @SuppressWarnings("unchecked")
+    private DefaultParameterDescriptor() {
+        final PropertyType<?,?> wrapper = Context.getWrapper(Context.current());
+        if (wrapper instanceof CC_OperationParameter) {
+            final CC_OperationParameter param = (CC_OperationParameter) wrapper;
+            /*
+             * This unsafe cast would be forbidden if this constructor was public or used in any context where the
+             * user can choose the value of <T>. But this constructor should be invoked only during unmarshalling,
+             * after the creation of the ParameterValue (this is the reverse creation order than what we normally
+             * do through the public API). The 'valueClass' should be compatible with DefaultParameterValue.value,
+             * and the parameterized type visible to the user should be only <?>.
+             */
+            valueClass  = (Class) param.valueClass;
+            valueDomain = param.valueDomain;
+        } else {
+            valueClass  = null;
+            valueDomain = null;
+        }
+        validValues  = null;
+        defaultValue = null;
+    }
+
+    /**
      * Constructs a descriptor from the given properties. The properties map is given unchanged to the
      * {@linkplain AbstractParameterDescriptor#AbstractParameterDescriptor(Map, int, int) super-class constructor}.
      * The following table is a reminder of main (not all) properties:

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -125,7 +125,7 @@ import java.nio.file.Path;
  */
 @XmlType(name = "ParameterValueType", propOrder = {
     "xmlValue",
-//  "operationParameter"
+    "descriptor"
 })
 @XmlRootElement(name = "ParameterValue")
 public class DefaultParameterValue<T> extends FormattableObject implements ParameterValue<T>,
@@ -138,8 +138,13 @@ public class DefaultParameterValue<T> ex
 
     /**
      * The definition of this parameter.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link #setDescriptor(ParameterDescriptor)}</p>
+     *
+     * @see #getDescriptor()
      */
-    private final ParameterDescriptor<T> descriptor;
+    private ParameterDescriptor<T> descriptor;
 
     /**
      * The value, or {@code null} if undefined.
@@ -160,7 +165,6 @@ public class DefaultParameterValue<T> ex
      * but will be assigned a value after XML unmarshalling.
      */
     private DefaultParameterValue() {
-        descriptor = null;
     }
 
     /**
@@ -199,6 +203,7 @@ public class DefaultParameterValue<T> ex
      * @return The definition of this parameter.
      */
     @Override
+    @XmlElement(name = "operationParameter", required = true)
     public ParameterDescriptor<T> getDescriptor() {
         return descriptor;
     }
@@ -525,7 +530,7 @@ public class DefaultParameterValue<T> ex
      */
     private String getClassTypeError() {
         return Errors.format(Errors.Keys.IllegalOperationForValueClass_1,
-                ((ParameterDescriptor<?>) descriptor).getValueClass());
+                (descriptor != null) ? ((ParameterDescriptor<?>) descriptor).getValueClass() : "?");
     }
 
     /**
@@ -919,8 +924,9 @@ public class DefaultParameterValue<T> ex
              * Note that we take the descriptor unit as a starting point instead than this parameter unit
              * in order to give precedence to the descriptor units in Convention.WKT1_COMMON_UNITS mode.
              */
-            Unit<?> contextualUnit = descriptor.getUnit();
-            if (contextualUnit == null) { // Should be very rare (probably a buggy descriptor), but we try to be safe.
+            Unit<?> contextualUnit;
+            if (descriptor == null || (contextualUnit = descriptor.getUnit()) == null) {
+                // Should be very rare (probably a buggy descriptor), but we try to be safe.
                 contextualUnit = unit;
             }
             contextualUnit = formatter.toContextualUnit(contextualUnit);
@@ -940,7 +946,13 @@ public class DefaultParameterValue<T> ex
             } catch (IllegalStateException exception) {
                 // May happen if a parameter is mandatory (e.g. "semi-major")
                 // but no value has been set for this parameter.
-                formatter.setInvalidWKT(descriptor, exception);
+                if (descriptor != null) {
+                    formatter.setInvalidWKT(descriptor, exception);
+                } else {
+                    // Null descriptor should be illegal but may happen after unmarshalling of invalid GML.
+                    // We make this WKT formatting robust since it is used by 'toString()' implementation.
+                    formatter.setInvalidWKT(DefaultParameterValue.class, exception);
+                }
                 value = Double.NaN;
             }
             formatter.append(value);
@@ -958,7 +970,13 @@ public class DefaultParameterValue<T> ex
                 if (!isWKT1) {
                     formatter.append(unit);
                 } else if (!ignoreUnits) {
-                    formatter.setInvalidWKT(descriptor, null);
+                    if (descriptor != null) {
+                        formatter.setInvalidWKT(descriptor, null);
+                    } else {
+                        // Null descriptor should be illegal but may happen after unmarshalling of invalid GML.
+                        // We make this WKT formatting robust since it is used by 'toString()' implementation.
+                        formatter.setInvalidWKT(DefaultParameterValue.class, null);
+                    }
                 }
             }
         }
@@ -1000,6 +1018,7 @@ public class DefaultParameterValue<T> ex
         @XmlElement(name = "valueList",         type = MeasureList.class)
     })
     private Object getXmlValue() {
+        final Object value = getValue();    // Give to user a chance to override.
         if (value != null) {
             if (value instanceof Number) {
                 final Number n = (Number) value;
@@ -1009,7 +1028,7 @@ public class DefaultParameterValue<T> ex
                         return xmlValue;
                     }
                 }
-                return new Measure(((Number) value).doubleValue(), unit);
+                return new Measure(((Number) value).doubleValue(), getUnit());
             }
             if (value instanceof CharSequence) {
                 return value.toString();
@@ -1022,7 +1041,7 @@ public class DefaultParameterValue<T> ex
                 if (Numbers.isInteger(type)) {
                     return new IntegerList(value);
                 }
-                return new MeasureList(value, type, unit);
+                return new MeasureList(value, type, getUnit());
             }
         }
         return value;
@@ -1031,6 +1050,7 @@ public class DefaultParameterValue<T> ex
     /**
      * Invoked by JAXB at unmarshalling time.
      */
+    @SuppressWarnings("unchecked")
     private void setXmlValue(Object xmlValue) {
         if (ReferencingUtilities.canSetProperty(DefaultParameterValue.class,
                 "setXmlValue", "value", value != null || unit != null))
@@ -1047,6 +1067,10 @@ public class DefaultParameterValue<T> ex
                 xmlValue = ((IntegerList) xmlValue).toArray();
             }
             if (descriptor != null) {
+                /*
+                 * Should never happen with default SIS implementation, but may happen if the user created
+                 * a sub-type of DefaultParameterValue with a default constructor providing the descriptor.
+                 */
                 value = ObjectConverters.convert(xmlValue, descriptor.getValueClass());
             } else {
                 /*
@@ -1054,12 +1078,23 @@ public class DefaultParameterValue<T> ex
                  * descriptor is normally defined after the value in a GML document. The type will need
                  * to be verified when the descriptor will be set.
                  *
-                 * There is no @SuppressWarnings("unchecked") annotation because we can not prove that this
-                 * cast is correct before the descriptor is set, and maybe that descriptor will never be set
-                 * (if the GML document is illegal).
+                 * There is no way we can prove that this cast is correct before the descriptor is set,
+                 * and maybe that descriptor will never be set if the GML document is illegal. However
+                 * this code is executed only during XML unmarshalling, in which case our unmarshalling
+                 * process will construct a descriptor compatible with the value rather than the converse.
                  */
                 value = (T) xmlValue;
             }
         }
     }
+
+    /**
+     * Invoked by JAXB at unmarshalling time.
+     *
+     * @see #getDescriptor()
+     */
+    private void setDescriptor(final ParameterDescriptor<T> descriptor) {
+        this.descriptor = descriptor;
+        assert (value == null) || descriptor.getValueClass().isInstance(value) : this;
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -645,7 +645,9 @@ public class ParameterFormat extends Tab
                  */
                 final ParameterDescriptor<?> descriptor = (ParameterDescriptor<?>) generalDescriptor;
                 final Class<?> valueClass = descriptor.getValueClass();
-                table.append(getFormat(Class.class).format(valueClass, buffer, dummyFP).toString());
+                if (valueClass != null) {  // Should never be null, but let be safe.
+                    table.append(getFormat(Class.class).format(valueClass, buffer, dummyFP).toString());
+                }
                 nextColumn(table);
                 buffer.setLength(0);
                 /*

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Parameters.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -171,6 +171,7 @@ public abstract class Parameters impleme
     public static <T> ParameterDescriptor<T> cast(final ParameterDescriptor<?> descriptor, final Class<T> valueClass)
             throws ClassCastException
     {
+        ArgumentChecks.ensureNonNull("valueClass", valueClass);
         if (descriptor != null) {
             final Class<?> actual = descriptor.getValueClass();
             // We require a strict equality - not type.isAssignableFrom(actual) - because in
@@ -187,9 +188,9 @@ public abstract class Parameters impleme
      * Casts the given parameter value to the given type.
      * An exception is thrown immediately if the parameter does not have the expected value class.
      *
-     * @param  <T>   The expected value class.
-     * @param  value The value to cast, or {@code null}.
-     * @param  type  The expected value class.
+     * @param  <T>        The expected value class.
+     * @param  parameter  The parameter to cast, or {@code null}.
+     * @param  valueClass The expected value class.
      * @return The value casted to the given type, or {@code null} if the given value was null.
      * @throws ClassCastException if the given value doesn't have the expected value class.
      *
@@ -198,18 +199,19 @@ public abstract class Parameters impleme
      * @category verification
      */
     @SuppressWarnings("unchecked")
-    public static <T> ParameterValue<T> cast(final ParameterValue<?> value, final Class<T> type)
+    public static <T> ParameterValue<T> cast(final ParameterValue<?> parameter, final Class<T> valueClass)
             throws ClassCastException
     {
-        if (value != null) {
-            final ParameterDescriptor<?> descriptor = value.getDescriptor();
+        ArgumentChecks.ensureNonNull("valueClass", valueClass);
+        if (parameter != null) {
+            final ParameterDescriptor<?> descriptor = parameter.getDescriptor();
             final Class<?> actual = descriptor.getValueClass();
-            if (!type.equals(actual)) { // Same comment than cast(ParameterDescriptor)...
+            if (!valueClass.equals(actual)) {   // Same comment than cast(ParameterDescriptor).
                 throw new ClassCastException(Errors.format(Errors.Keys.IllegalParameterType_2,
                         descriptor.getName().getCode(), actual));
             }
         }
-        return (ParameterValue<T>) value;
+        return (ParameterValue<T>) parameter;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Verifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Verifier.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Verifier.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/Verifier.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -22,6 +22,7 @@ import java.lang.reflect.Array;
 import javax.measure.unit.Unit;
 import javax.measure.converter.UnitConverter;
 import javax.measure.converter.ConversionException;
+import org.opengis.metadata.Identifier;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.GeneralParameterDescriptor;
 import org.opengis.parameter.InvalidParameterValueException;
@@ -29,6 +30,7 @@ import org.apache.sis.measure.Range;
 import org.apache.sis.measure.Units;
 import org.apache.sis.util.Numbers;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Vocabulary;
 
 
 /**
@@ -92,7 +94,6 @@ final class Verifier {
      *         then casted to the descriptor parameterized type.
      * @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
     {
@@ -145,7 +146,7 @@ final class Verifier {
                          */
                         Number n = converter.convert(((Number) value).doubleValue());
                         try {
-                            convertedValue = Numbers.cast(n, (Class<? extends Number>) valueClass);
+                            convertedValue = Numbers.cast(n, valueClass.asSubclass(Number.class));
                         } catch (IllegalArgumentException e) {
                             throw new InvalidParameterValueException(e.getLocalizedMessage(), getName(descriptor), value);
                         }
@@ -161,7 +162,7 @@ final class Verifier {
                             Number n = (Number) Array.get(value, i);
                             n = converter.convert(n.doubleValue()); // Value in units that we can compare.
                             try {
-                                n = Numbers.cast(n, (Class<? extends Number>) componentType);
+                                n = Numbers.cast(n, componentType.asSubclass(Number.class));
                             } catch (IllegalArgumentException e) {
                                 throw new InvalidParameterValueException(e.getLocalizedMessage(),
                                         getName(descriptor) + '[' + i + ']', value);
@@ -193,7 +194,7 @@ final class Verifier {
                 throw new InvalidParameterValueException(error.message(null, name, value), name, value);
             }
         }
-        return (T) convertedValue;
+        return valueClass.cast(convertedValue);
     }
 
     /**
@@ -313,7 +314,16 @@ final class Verifier {
      * Consequently, we may consider to returns a localized name in a future version.
      */
     static String getName(final GeneralParameterDescriptor descriptor) {
-        return descriptor.getName().getCode();
+        if (descriptor != null) {
+            final Identifier name = descriptor.getName();
+            if (name != null) {
+                final String code = name.getCode();
+                if (code != null) {
+                    return code;
+                }
+            }
+        }
+        return Vocabulary.format(Vocabulary.Keys.Unnamed);
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/package-info.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/package-info.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/package-info.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -93,6 +93,9 @@
     @XmlNs(prefix = "xsi", namespaceURI = Namespaces.XSI)
 })
 @XmlAccessorType(XmlAccessType.NONE)
+@XmlJavaTypeAdapters({
+    @XmlJavaTypeAdapter(CC_OperationParameter.class)
+})
 package org.apache.sis.parameter;
 
 import javax.xml.bind.annotation.XmlNs;
@@ -100,4 +103,7 @@ import javax.xml.bind.annotation.XmlNsFo
 import javax.xml.bind.annotation.XmlSchema;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
+import org.apache.sis.internal.jaxb.referencing.*;
 import org.apache.sis.xml.Namespaces;

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -123,6 +123,7 @@ import java.util.Objects;
  * @module
  */
 @XmlType(name="IdentifiedObjectType", propOrder={
+    "description",
     "identifier",
     "names",
     "remarks"
@@ -705,6 +706,25 @@ public class AbstractIdentifiedObject ex
     }
 
     /**
+     * Returns a narrative explanation of the role of this object.
+     *
+     * <div class="section">Default value</div>
+     * The default implementation returns the
+     * {@linkplain org.apache.sis.metadata.iso.ImmutableIdentifier#getDescription() description}
+     * provided by this object's {@linkplain #getName() name}.
+     *
+     * @return A narrative explanation of the role of this object, or {@code null} if none.
+     *
+     * @see org.apache.sis.metadata.iso.ImmutableIdentifier#getDescription()
+     *
+     * @since 0.6
+     */
+    @XmlElement
+    public InternationalString getDescription() {
+        return (name != null) ? name.getDescription() : null;
+    }
+
+    /**
      * Returns comments on or information about this object, including data source information.
      * If this object {@linkplain #isDeprecated() is deprecated}, then the remarks should give
      * indication about the replacement (e.g. <cite>"superceded by …"</cite>).

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterMarshallingTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterMarshallingTest.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterMarshallingTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterMarshallingTest.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -21,6 +21,8 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import javax.xml.bind.JAXBException;
 import javax.measure.unit.SI;
+import org.opengis.test.Validators;
+import org.opengis.parameter.ParameterDescriptor;
 import org.apache.sis.measure.Range;
 import org.apache.sis.measure.MeasurementRange;
 import org.apache.sis.test.DependsOn;
@@ -51,7 +53,8 @@ public final strictfp class ParameterMar
      */
     private static <T> DefaultParameterValue<T> create(final Class<T> type, final Range<?> valueDomain) {
         return new DefaultParameterValue<>(new DefaultParameterDescriptor<>(
-                Collections.singletonMap(DefaultParameterDescriptor.NAME_KEY, type.getSimpleName()),
+                Collections.singletonMap(DefaultParameterDescriptor.NAME_KEY,
+                        "A parameter of type " + type.getSimpleName()),
                 1, 1, type, valueDomain, null, null));
     }
 
@@ -68,9 +71,54 @@ public final strictfp class ParameterMar
         assertXmlEquals(expected, xml, "xmlns:*");
         final DefaultParameterValue<?> r = (DefaultParameterValue<?>) XML.unmarshal(xml);
         if (!Objects.deepEquals(parameter.getValue(), r.getValue())) {
-            assertEquals("value", parameter.getValue(), r.getValue());  // Should always fail, but we want the error message.
+            // If we enter in this block, then the line below should always fail.
+            // But we use this assertion for getting a better error message.
+            assertEquals("value", parameter.getValue(), r.getValue());
         }
-        assertEquals("unit",  parameter.getUnit(),  r.getUnit());
+        assertEquals("unit", parameter.getUnit(), r.getUnit());
+        /*
+         * Verify the descriptor, especially the 'valueClass' property. That property is not part of GML,
+         * so Apache SIS has to rely on some tricks for finding this information (see CC_OperationParameter).
+         */
+        final ParameterDescriptor<?> reference = parameter.getDescriptor();
+        final ParameterDescriptor<?> descriptor = r.getDescriptor();
+        assertNotNull("descriptor",                                             descriptor);
+        assertEquals ("descriptor.name",          reference.getName(),          descriptor.getName());
+        assertEquals ("descriptor.unit",          reference.getUnit(),          descriptor.getUnit());
+        assertEquals ("descriptor.valueClass",    reference.getValueClass(),    descriptor.getValueClass());
+        assertEquals ("descriptor.minimumOccurs", reference.getMinimumOccurs(), descriptor.getMinimumOccurs());
+        assertEquals ("descriptor.maximumOccurs", reference.getMaximumOccurs(), descriptor.getMaximumOccurs());
+        Validators.validate(r);
+    }
+
+    /**
+     * Tests (un)marshalling of a parameter descriptor.
+     *
+     * @throws JAXBException if an error occurred during marshalling or unmarshalling.
+     */
+    @Test
+    public void testDescriptor() throws JAXBException {
+        final DefaultParameterDescriptor<Double> descriptor = new DefaultParameterDescriptor<>(
+                Collections.singletonMap(DefaultParameterDescriptor.NAME_KEY, "A descriptor"),
+                0, 1, Double.class, null, null, null);
+        final String xml = XML.marshal(descriptor);
+        assertXmlEquals(
+                "<gml:OperationParameter xmlns:gml=\"" + Namespaces.GML + "\">\n"
+              + "  <gml:name>A descriptor</gml:name>\n"
+              + "  <gml:minimumOccurs>0</gml:minimumOccurs>\n"
+              + "</gml:OperationParameter>", xml, "xmlns:*");
+        final DefaultParameterDescriptor<?> r = (DefaultParameterDescriptor<?>) XML.unmarshal(xml);
+        assertEquals("name", "A descriptor", r.getName().getCode());
+        assertEquals("minimumOccurs", 0, r.getMinimumOccurs());
+        assertEquals("maximumOccurs", 1, r.getMaximumOccurs());
+        /*
+         * A DefaultParameterDescriptor with null 'valueClass' is illegal, but there is no way we can guess
+         * this information if the <gml:OperationParameter> element was not a child of <gml:ParameterValue>.
+         * The current implementation leaves 'valueClass' to null despite being illegal. This behavior may
+         * change in any future Apache SIS version.
+         */
+        assertNull("valueDomain", r.getValueDomain());
+        assertNull("valueClass",  r.getValueClass());   // May change in any future SIS release.
     }
 
     /**
@@ -79,12 +127,18 @@ public final strictfp class ParameterMar
      * @throws JAXBException if an error occurred during marshalling or unmarshalling.
      */
     @Test
+    @DependsOnMethod("testDescriptor")
     public void testStringValue() throws JAXBException {
         final DefaultParameterValue<String> parameter = create(String.class, null);
         parameter.setValue("A string value");
         testMarshallAndUnmarshall(parameter,
                 "<gml:ParameterValue xmlns:gml=\"" + Namespaces.GML + "\">\n"
               + "  <gml:stringValue>A string value</gml:stringValue>\n"
+              + "    <gml:operationParameter>"
+              + "      <gml:OperationParameter>"
+              + "        <gml:name>A parameter of type String</gml:name>"
+              + "      </gml:OperationParameter>"
+              + "    </gml:operationParameter>"
               + "</gml:ParameterValue>");
     }
 
@@ -102,6 +156,11 @@ public final strictfp class ParameterMar
         testMarshallAndUnmarshall(parameter,
                 "<gml:ParameterValue xmlns:gml=\"" + Namespaces.GML + "\">\n"
               + "  <gml:valueFile>http://www.opengis.org</gml:valueFile>\n"
+              + "    <gml:operationParameter>"
+              + "      <gml:OperationParameter>"
+              + "        <gml:name>A parameter of type URI</gml:name>"
+              + "      </gml:OperationParameter>"
+              + "    </gml:operationParameter>"
               + "</gml:ParameterValue>");
     }
 
@@ -118,6 +177,11 @@ public final strictfp class ParameterMar
         testMarshallAndUnmarshall(parameter,
                 "<gml:ParameterValue xmlns:gml=\"" + Namespaces.GML + "\">\n" 
               + "  <gml:booleanValue>true</gml:booleanValue>\n"
+              + "    <gml:operationParameter>"
+              + "      <gml:OperationParameter>"
+              + "        <gml:name>A parameter of type Boolean</gml:name>"
+              + "      </gml:OperationParameter>"
+              + "    </gml:operationParameter>"
               + "</gml:ParameterValue>");
     }
 
@@ -134,6 +198,11 @@ public final strictfp class ParameterMar
         testMarshallAndUnmarshall(parameter,
                 "<gml:ParameterValue xmlns:gml=\"" + Namespaces.GML + "\">\n" 
               + "  <gml:integerValue>2000</gml:integerValue>\n"
+              + "    <gml:operationParameter>"
+              + "      <gml:OperationParameter>"
+              + "        <gml:name>A parameter of type Integer</gml:name>"
+              + "      </gml:OperationParameter>"
+              + "    </gml:operationParameter>"
               + "</gml:ParameterValue>");
     }
 
@@ -150,6 +219,11 @@ public final strictfp class ParameterMar
         testMarshallAndUnmarshall(parameter,
                 "<gml:ParameterValue xmlns:gml=\"" + Namespaces.GML + "\">\n"
               + "  <gml:integerValueList>101 105 208</gml:integerValueList>\n"
+              + "    <gml:operationParameter>"
+              + "      <gml:OperationParameter>"
+              + "        <gml:name>A parameter of type int[]</gml:name>"
+              + "      </gml:OperationParameter>"
+              + "    </gml:operationParameter>"
               + "</gml:ParameterValue>");
     }
 
@@ -167,6 +241,11 @@ public final strictfp class ParameterMar
         testMarshallAndUnmarshall(parameter,
                 "<gml:ParameterValue xmlns:gml=\"" + Namespaces.GML + "\">\n" 
               + "  <gml:value uom=\"urn:ogc:def:uom:EPSG::9001\">3000.0</gml:value>\n"
+              + "    <gml:operationParameter>"
+              + "      <gml:OperationParameter>"
+              + "        <gml:name>A parameter of type Double</gml:name>"
+              + "      </gml:OperationParameter>"
+              + "    </gml:operationParameter>"
               + "</gml:ParameterValue>");
     }
 
@@ -184,6 +263,11 @@ public final strictfp class ParameterMar
         testMarshallAndUnmarshall(parameter,
                 "<gml:ParameterValue xmlns:gml=\"" + Namespaces.GML + "\">\n"
               + "  <gml:valueList uom=\"urn:ogc:def:uom:EPSG::9001\">203.0 207.0 204.0</gml:valueList>\n"
+              + "    <gml:operationParameter>"
+              + "      <gml:OperationParameter>"
+              + "        <gml:name>A parameter of type double[]</gml:name>"
+              + "      </gml:OperationParameter>"
+              + "    </gml:operationParameter>"
               + "</gml:ParameterValue>");
     }
 }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -29,6 +29,7 @@ import org.apache.sis.util.logging.Warni
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Messages;
 import org.apache.sis.util.resources.IndexedResourceBundle;
+import org.apache.sis.internal.jaxb.gco.PropertyType;
 import org.apache.sis.internal.system.Semaphores;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.xml.MarshalContext;
@@ -37,16 +38,12 @@ import org.apache.sis.xml.ReferenceResol
 
 
 /**
- * Thread-local status of a marshalling or unmarshalling processes, also occasionally used for other processes.
+ * Thread-local status of a marshalling or unmarshalling processes.
  * All non-static methods in this class except {@link #finish()} are implementation of public API.
  * All static methods are internal API. Those methods expect a {@code Context} instance as their first argument.
  * They should be though as if they were normal member methods, except that they accept {@code null} instance
  * if no (un)marshalling is in progress.
  *
- * <p>While this class is primarily used for (un)marshalling processes, it may also be opportunistically used
- * for other processes like {@link org.apache.sis.metadata.AbstractMetadata#equals(Object)}. The class name is
- * only "{@code Context}" for that reason.</p>
- *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
  * @version 0.5
@@ -120,34 +117,46 @@ public final class Context extends Marsh
      * The timezone, or {@code null} if unspecified.
      * In the later case, an implementation-default (typically UTC) timezone is used.
      */
-    private TimeZone timezone;
+    private final TimeZone timezone;
 
     /**
      * The base URL of ISO 19139 (or other standards) schemas. The valid values
      * are documented in the {@link org.apache.sis.xml.XML#SCHEMAS} property.
      */
-    private Map<String,String> schemas;
+    private final Map<String,String> schemas;
 
     /**
      * The GML version to be marshalled or unmarshalled, or {@code null} if unspecified.
      * If null, than the latest version is assumed.
      */
-    private Version versionGML;
+    private final Version versionGML;
 
     /**
      * The reference resolver currently in use, or {@code null} for {@link ReferenceResolver#DEFAULT}.
      */
-    private ReferenceResolver resolver;
+    private final ReferenceResolver resolver;
 
     /**
      * The value converter currently in use, or {@code null} for {@link ValueConverter#DEFAULT}.
      */
-    private ValueConverter converter;
+    private final ValueConverter converter;
 
     /**
      * The object to inform about warnings, or {@code null} if none.
      */
-    private WarningListener<?> warningListener;
+    private final WarningListener<?> warningListener;
+
+    /**
+     * The {@code <gml:*PropertyType>} which is wrapping the {@code <gml:*Type>} object to (un)marshal, or
+     * {@code null} if this information is not provided. See {@link #getWrapper(Context)} for an example.
+     *
+     * <p>For performance reasons, this {@code wrapper} information is not provided by default.
+     * See {@link #setWrapper(Context, PropertyType)} for more information.</p>
+     *
+     * @see #getWrapper(Context)
+     * @see #setWrapper(Context, PropertyType)
+     */
+    private PropertyType<?,?> wrapper;
 
     /**
      * The context which was previously used. This form a linked list allowing to push properties
@@ -177,6 +186,7 @@ public final class Context extends Marsh
      * @param  converter       The converter in use.
      * @param  warningListener The object to inform about warnings.
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public Context(final int                bitMasks,
                    final Locale             locale,   final TimeZone       timezone,
                    final Map<String,String> schemas,  final Version        versionGML,
@@ -191,13 +201,13 @@ public final class Context extends Marsh
         this.resolver        = resolver;
         this.converter       = converter;
         this.warningListener = warningListener;
-        previous = current();
-        CURRENT.set(this);
         if ((bitMasks & MARSHALLING) != 0) {
             if (!Semaphores.queryAndSet(Semaphores.NULL_COLLECTION)) {
                 this.bitMasks |= CLEAR_SEMAPHORE;
             }
         }
+        previous = current();
+        CURRENT.set(this);
     }
 
     /**
@@ -207,16 +217,24 @@ public final class Context extends Marsh
      *
      * @see #push(Locale)
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     private Context(final Context previous) {
         if (previous != null) {
-            bitMasks         = previous.bitMasks;
-            locale           = previous.locale;
-            timezone         = previous.timezone;
-            schemas          = previous.schemas;
-            versionGML       = previous.versionGML;
-            resolver         = previous.resolver;
-            converter        = previous.converter;
-            warningListener  = previous.warningListener;
+            bitMasks        = previous.bitMasks;
+            locale          = previous.locale;
+            timezone        = previous.timezone;
+            schemas         = previous.schemas;
+            versionGML      = previous.versionGML;
+            resolver        = previous.resolver;
+            converter       = previous.converter;
+            warningListener = previous.warningListener;
+        } else {
+            timezone        = null;
+            schemas         = null;
+            versionGML      = null;
+            resolver        = null;
+            converter       = null;
+            warningListener = null;
         }
         this.previous = previous;
         CURRENT.set(this);
@@ -320,6 +338,57 @@ public final class Context extends Marsh
     }
 
     /**
+     * Returns the {@code <gml:*PropertyType>} which is wrapping the {@code <gml:*Type>} object to (un)marshal,
+     * or {@code null} if this information is not provided. The {@code <gml:*PropertyType>} element can contains
+     * information not found in {@code <gml:*Type>} objects like XLink or UUID.
+     *
+     * <div class="note"><b>Example:</b>
+     * before unmarshalling the {@code <gml:OperationParameter>} (upper case {@code O}) element below,
+     * {@code wrapper} will be set to the temporary object representing {@code <gml:operationParameter>}.
+     * That adapter provides important information for the SIS {@code <gml:OperationParameter>} constructor.
+     *
+     * {@preformat xml
+     *   <gml:ParameterValue>
+     *     <gml:valueFile>http://www.opengis.org</gml:valueFile>
+     *     <gml:operationParameter>
+     *       <gml:OperationParameter>
+     *         <gml:name>A parameter of type URI</gml:name>
+     *       </gml:OperationParameter>
+     *     </gml:operationParameter>
+     *   </gml:ParameterValue>
+     * }</div>
+     *
+     * For performance reasons, this {@code wrapper} information is not provided by default.
+     * See {@link #setWrapper(Context, PropertyType)} for more information.
+     *
+     * @param  context The current context, or {@code null} if none.
+     * @return The {@code <gml:*PropertyType>} which is wrapping the {@code <gml:*Type>} object to (un)marshal,
+     *         or {@code null} if unknown.
+     */
+    public static PropertyType<?,?> getWrapper(final Context context) {
+        return (context != null) ? context.wrapper : null;
+    }
+
+    /**
+     * Invoked by {@link PropertyType} implementations for declaring the {@code <gml:*PropertyType>}
+     * instance which is wrapping the {@code <gml:*Type>} object to (un)marshal.
+     *
+     * <p>For performance reasons, this {@code wrapper} information is not provided by default.
+     * To get this information, the {@code PropertyType} implementation needs to define the
+     * {@code beforeUnmarshal(…)} method. For an implementation example, see
+     * {@link org.apache.sis.internal.jaxb.referencing.CC_OperationParameter}.</p>
+     *
+     * @param context The current context, or {@code null} if none.
+     * @param wrapper The {@code <gml:*PropertyType>} which is wrapping the {@code <gml:*Type>} object to (un)marshal,
+     *                or {@code null} if unknown.
+     */
+    public static void setWrapper(final Context context, final PropertyType<?,?> wrapper) {
+        if (context != null) {
+            context.wrapper = wrapper;
+        }
+    }
+
+    /**
      * Returns {@code true} if the GML version is equals or newer than the specified version.
      * If no GML version were specified, then this method returns {@code true}, i.e. newest
      * version is assumed.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/PropertyType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/PropertyType.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/PropertyType.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/PropertyType.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -50,7 +50,7 @@ import org.apache.sis.util.iso.SimpleInt
  *   </CI_ResponsibleParty>
  * }
  *
- * The {@code </CI_Contact>} level is not really necessary, and JAXB is not designed for inserting
+ * The {@code <CI_Contact>} level is not really necessary, and JAXB is not designed for inserting
  * such level since it is not the usual way to write XML. In order to get this output with JAXB,
  * we have to wrap metadata object in an additional object. So each {@code PropertyType} subclass
  * is both a JAXB adapter and a wrapper. We have merged those functionalities in order to avoid

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/NumberRange.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/NumberRange.java?rev=1696513&r1=1696512&r2=1696513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/NumberRange.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/NumberRange.java [UTF-8] Wed Aug 19 02:35:11 2015
@@ -208,7 +208,7 @@ public class NumberRange<E extends Numbe
         if (Float.isNaN(value)) {
             throw new IllegalArgumentException(Errors.format(Errors.Keys.NotANumber_1, name));
         }
-        return (value != infinity) ? Float.valueOf(value) : null;
+        return (value != infinity) ? value : null;
     }
 
     /**



Mime
View raw message