sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1700283 - 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/operation/ sis-r...
Date Mon, 31 Aug 2015 17:52:00 GMT
Author: desruisseaux
Date: Mon Aug 31 17:52:00 2015
New Revision: 1700283

URL: http://svn.apache.org/r1700283
Log:
Consolidation of JAXB annotations on DefaultOperationMethod and parameters:
- Delegate more works to JAXB adapter classes.
- More effort for merging information provided by duplicated parameter descriptors.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationMethod.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameterGroup.java
    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/DefaultParameterDescriptorGroup.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValueGroup.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterValueGroupWrapper.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/OperationMarshallingTest.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/util/CollectionsExt.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/CollectionsExtTest.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -16,20 +16,40 @@
  */
 package org.apache.sis.internal.jaxb.referencing;
 
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
 import javax.xml.bind.annotation.XmlElementRef;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.GeneralParameterDescriptor;
+import org.opengis.parameter.ParameterNotFoundException;
 import org.apache.sis.parameter.AbstractParameterDescriptor;
 import org.apache.sis.parameter.DefaultParameterDescriptor;
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
+import org.apache.sis.parameter.Parameters;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.jaxb.gco.PropertyType;
+import org.apache.sis.internal.jaxb.Context;
 
 
 /**
  * JAXB adapter mapping implementing class to the GeoAPI interface. See
  * package documentation for more information about JAXB and interface.
  *
+ * <p>This class provides an additional {@link #replacement(GeneralParameterDescriptor, GeneralParameterDescriptor)}
+ * method building a unique descriptor instance when the same descriptor is declared in more than one place in the
+ * GML document. Some examples of duplications are:</p>
+ *
+ * <ul>
+ *   <li>The descriptors listed under the {@code <gml:group>} element, which duplicate the descriptors listed
+ *       under each {@code <gml:parameterValue>} element.</li>
+ *   <li>The descriptors declared in each parameter value of a {@code SingleOperation}, which duplicate the
+ *       descriptors declared in the associated {@code OperationMethod}.</li>
+ * </ul>
+ *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
  * @version 0.6
@@ -37,6 +57,31 @@ import org.apache.sis.internal.jaxb.gco.
  */
 public final class CC_GeneralOperationParameter extends PropertyType<CC_GeneralOperationParameter, GeneralParameterDescriptor> {
     /**
+     * The default value of {@code minimumOccurs} and {@code maximumOccurs} if the XML element is not provided.
+     */
+    public static final short DEFAULT_OCCURRENCE = 1;
+
+    /**
+     * The properties to ignore in the descriptor parsed from GML when this descriptor is merged with a
+     * pre-defined descriptor. Remarks:
+     *
+     * <ul>
+     *   <li>We ignore the name because the comparisons shall be performed by the caller with
+     *       {@link IdentifiedObjects#isHeuristicMatchForName} or something equivalent.</li>
+     *   <li>We ignore aliases and identifiers for now for avoiding the additional complexity
+     *       of dealing with collections, and because the Apache SIS pre-defined descriptors
+     *       will be more complete in a majority of case.
+     *
+     *       <b>TODO - </b> this may be revised in any future SIS version.</li>
+     * </ul>
+     */
+    private static final String[] IGNORE_DURING_MERGE = {
+        GeneralParameterDescriptor.NAME_KEY,
+        GeneralParameterDescriptor.ALIAS_KEY,
+        GeneralParameterDescriptor.IDENTIFIERS_KEY
+    };
+
+    /**
      * Empty constructor for JAXB only.
      */
     public CC_GeneralOperationParameter() {
@@ -105,4 +150,167 @@ public final class CC_GeneralOperationPa
     public void setElement(final AbstractParameterDescriptor parameter) {
         metadata = parameter;
     }
+
+    /**
+     * Returns a descriptor with the same properties than the {@code provided} one, but completed with information
+     * not found in GML. Those missing information are given by the {@code complete} descriptor, which may come from
+     * two sources:
+     *
+     * <ul>
+     *   <li>The descriptor for a {@code <gml:ParameterValue>} element. Those descriptors are more complete than the
+     *       ones provided by {@code <gml:OperationParameter>} elements alone because the parameter value allows SIS
+     *       to infer the {@code valueClass}.</li>
+     *   <li>A pre-defined parameter descriptor from the {@link org.apache.sis.internal.referencing.provider} package.</li>
+     * </ul>
+     *
+     * @param  provided The descriptor unmarshalled from the GML document.
+     * @param  complete The descriptor to use for completing missing information.
+     * @return The descriptor to use. May be one of the arguments given to this method, or a new instance.
+     */
+    public static GeneralParameterDescriptor replacement(final GeneralParameterDescriptor provided,
+                                                         final GeneralParameterDescriptor complete)
+    {
+        if (provided == complete) {
+            return complete;
+        }
+        final boolean isGroup;
+        if (provided instanceof ParameterDescriptor<?> && complete instanceof ParameterDescriptor<?>) {
+            isGroup = false;    // This is by far the most usual case.
+        } else if (provided instanceof ParameterDescriptorGroup && complete instanceof ParameterDescriptorGroup) {
+            isGroup = true;
+        } else {
+            /*
+             * Mismatched or unknown type. It should not happen with descriptors parsed by JAXB and with
+             * pre-defined descriptors provided by SIS. But it could happen with a pre-defined descriptor
+             * found in a user-provided OperationMethod with malformed parameters.
+             * Return the descriptor found in the GML document as-is.
+             */
+            return provided;
+        }
+        final int minimumOccurs = provided.getMinimumOccurs();
+        final int maximumOccurs = provided.getMaximumOccurs();
+        final Map<String,?> expected = IdentifiedObjects.getProperties(complete);
+        final Map<String,?> actual   = IdentifiedObjects.getProperties(provided, IGNORE_DURING_MERGE);
+        final boolean canSubstitute  = complete.getMinimumOccurs() == minimumOccurs
+                                    && complete.getMaximumOccurs() == maximumOccurs
+                                    && expected.entrySet().containsAll(actual.entrySet());
+        if (canSubstitute && !isGroup) {
+            /*
+             * The pre-defined or ParameterValue descriptor contains at least all the information found
+             * in the descriptor parsed from the GML document, ignoring IGNORE_DURING_MERGE properties.
+             * So we can use the existing instance directly, assuming that the additional properties and
+             * the difference in ignored properties are acceptable.
+             */
+            return complete;
+        }
+        /*
+         * Collect the properties specified in the GML document and complete with the properties provided
+         * by the 'complete' descriptor. If the descriptor is a group, then this 'replacement' method will
+         * be invoked recursively for each parameter in the group.
+         */
+        final Map<String,Object> merged = new HashMap<>(expected);
+        merged.putAll(actual);  // May overwrite pre-defined properties.
+        if (isGroup) {
+            final List<GeneralParameterDescriptor> descriptors = ((ParameterDescriptorGroup) provided).descriptors();
+            return merge(actual, merged, minimumOccurs, maximumOccurs,
+                    descriptors.toArray(new GeneralParameterDescriptor[descriptors.size()]),
+                    (ParameterDescriptorGroup) complete, canSubstitute);
+        } else {
+            return merge(merged, (ParameterDescriptor<?>) provided, (ParameterDescriptor<?>) complete);
+        }
+    }
+
+    /**
+     * Returns a descriptor with the given properties, completed with information not found in GML.
+     * Those extra information are given by the {@code complete} descriptor.
+     *
+     * @param  properties    Properties as declared in the GML document, to be used if {@code complete} is incompatible.
+     * @param  merged        More complete properties, to be used if {@code complete} is compatible.
+     * @param  minimumOccurs Value to assign to {@link DefaultParameterDescriptorGroup#getMinimumOccurs()}.
+     * @param  maximumOccurs Value to assign to {@link DefaultParameterDescriptorGroup#getMaximumOccurs()}.
+     * @param  provided      Parameter descriptors declared in the GML document. This array will be overwritten.
+     * @param  complete      More complete parameter descriptors.
+     * @param  canSubstitute {@code true} if this method is allowed to return {@code complete}.
+     * @return The parameter descriptor group to use (may be the {@code complete} instance).
+     */
+    static ParameterDescriptorGroup merge(final Map<String,?>                properties,
+                                          final Map<String,?>                merged,
+                                          final int                          minimumOccurs,
+                                          final int                          maximumOccurs,
+                                          final GeneralParameterDescriptor[] provided,
+                                          final ParameterDescriptorGroup     complete,
+                                          boolean                            canSubstitute)
+    {
+        boolean isCompatible = true;
+        final Map<GeneralParameterDescriptor,Boolean> included = new IdentityHashMap<>(provided.length);
+        for (int i=0; i<provided.length; i++) {
+            final GeneralParameterDescriptor p = provided[i];
+            try {
+                /*
+                 * Replace the descriptors provided in the GML document by descriptors from the 'complete' instance,
+                 * if possible. Keep trace of the complete descriptors that we found in this process.
+                 */
+                GeneralParameterDescriptor predefined = complete.descriptor(p.getName().getCode());
+                if (predefined != null) {   // Safety in case 'complete' is a user's implementation.
+                    canSubstitute &= (provided[i] = replacement(p, predefined)) == predefined;
+                    included.put(predefined, Boolean.TRUE);
+                    continue;
+                }
+            } catch (ParameterNotFoundException e) {
+                Context.warningOccured(Context.current(), CC_GeneralOperationParameter.class, "replacement", e, canSubstitute);
+            }
+            /*
+             * If a parameter was not found in the 'complete' descriptor, we will not be able to use that descriptor.
+             * But we may still be able to use its properties (name, alias, identifier) provided that the parameter
+             * not found was optional.
+             */
+            isCompatible &= p.getMinimumOccurs() == 0;
+            canSubstitute = false;
+        }
+        if (isCompatible) {
+            /*
+             * At this point, we determined that all mandatory parameters in the GML document exist in the 'complete'
+             * descriptor. However the converse is not necessarily true. Verify that all parameters missing in the GML
+             * document were optional.
+             */
+            for (final GeneralParameterDescriptor descriptor : complete.descriptors()) {
+                if (!included.containsKey(descriptor) && descriptor.getMinimumOccurs() != 0
+                        && !CC_OperationMethod.isImplicitParameter(descriptor))
+                {
+                    canSubstitute = false;
+                    isCompatible  = false;
+                    break;
+                }
+            }
+        }
+        if (canSubstitute) {
+            return complete;
+        } else {
+            return new DefaultParameterDescriptorGroup(isCompatible ? merged : properties,
+                    minimumOccurs, maximumOccurs, provided);
+        }
+    }
+
+    /**
+     * Creates a new descriptor with the same properties than the {@code provided} one, but completed with
+     * information not found in GML. Those extra information are given by the {@code complete} descriptor.
+     *
+     * <p>It is the caller's responsibility to construct the {@code properties} map as a merge
+     * of the properties of the two given descriptors.</p>
+     */
+    private static <T> ParameterDescriptor<T> merge(final Map<String,?>          merged,
+                                                    final ParameterDescriptor<?> provided,
+                                                    final ParameterDescriptor<T> complete)
+    {
+        final Class<T> valueClass = complete.getValueClass();
+        return new DefaultParameterDescriptor<>(merged,
+                provided.getMinimumOccurs(),
+                provided.getMaximumOccurs(),
+                // Values below this point are not provided in GML documents,
+                // so they must be inferred from the pre-defined descriptor.
+                valueClass,
+                Parameters.getValueDomain(complete),
+                CollectionsExt.toArray(complete.getValidValues(), valueClass),
+                complete.getDefaultValue());
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationMethod.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationMethod.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationMethod.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationMethod.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -16,10 +16,24 @@
  */
 package org.apache.sis.internal.jaxb.referencing;
 
+import java.util.Map;
+import java.util.Collections;
 import javax.xml.bind.annotation.XmlElement;
+import org.opengis.util.FactoryException;
+import org.opengis.metadata.Identifier;
+import org.opengis.parameter.GeneralParameterValue;
+import org.opengis.parameter.GeneralParameterDescriptor;
+import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.CoordinateOperationFactory;
+import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.internal.jaxb.gco.PropertyType;
+import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.internal.referencing.provider.MapProjection;
+import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
 import org.apache.sis.referencing.operation.DefaultOperationMethod;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.util.ArraysExt;
 
 
 /**
@@ -89,4 +103,87 @@ public final class CC_OperationMethod ex
     public void setElement(final DefaultOperationMethod method) {
         metadata = method;
     }
+
+    /**
+     * Returns the given descriptors, excluding the implicit {@link MapProjection} parameters.
+     *
+     * @param  array The parameters to filter.
+     * @return The filtered parameters.
+     */
+    public static GeneralParameterValue[] filterImplicit(final GeneralParameterValue[] array) {
+        int n = 0;
+        for (final GeneralParameterValue value : array) {
+            if (!CC_OperationMethod.isImplicitParameter(value.getDescriptor())) {
+                array[n++] = value;
+            }
+        }
+        return ArraysExt.resize(array, n);
+    }
+
+    /**
+     * Returns the given descriptors, excluding the implicit {@link MapProjection} parameters.
+     *
+     * @param  array The parameters to filter.
+     * @return The filtered parameters.
+     */
+    public static GeneralParameterDescriptor[] filterImplicit(final GeneralParameterDescriptor[] array) {
+        int n = 0;
+        for (final GeneralParameterDescriptor descriptor : array) {
+            if (!CC_OperationMethod.isImplicitParameter(descriptor)) {
+                array[n++] = descriptor;
+            }
+        }
+        return ArraysExt.resize(array, n);
+    }
+
+    /**
+     * Returns {@code true} if the given descriptor is for an implicit parameter which should be excluded from GML.
+     *
+     * @param  descriptor The parameter descriptor to test.
+     * @return {@code true} if the given parameter should be omitted in the GML document.
+     */
+    static boolean isImplicitParameter(final GeneralParameterDescriptor descriptor) {
+        return descriptor == MapProjection.SEMI_MAJOR
+            || descriptor == MapProjection.SEMI_MINOR;
+    }
+
+    /**
+     * Wraps the given descriptors in a descriptor group of the given name. If the given name can be matched
+     * to the name of one of the predefined operation method, then the predefined parameters will be used.
+     *
+     * <p>We try to use predefined parameters if possible because they contain information, especially the
+     * {@link org.opengis.parameter.ParameterDescriptor#getValueClass()} property, which are not available
+     * in the GML document.</p>
+     *
+     * <div class="note"><b>Note:</b>
+     * this code is defined in this {@code CC_OperationMethod} class instead than in the
+     * {@link DefaultOperationMethod} class in the hope to reduce the amount of code processed
+     * by the JVM in the common case where JAXB (un)marshalling is not needed.</div>
+     *
+     * @param  name        The operation method name, to be also given to the descriptor group.
+     * @param  descriptors The parameter descriptors to wrap in a group. This array will be modified in-place.
+     * @return A parameter group containing at least the given descriptors, or equivalent descriptors.
+     */
+    public static ParameterDescriptorGroup group(final Identifier name, final GeneralParameterDescriptor[] descriptors) {
+        final CoordinateOperationFactory factory = DefaultFactories.forClass(CoordinateOperationFactory.class);
+        OperationMethod method = null;
+        if (factory != null) try {
+            method = factory.getOperationMethod(name.getCode());
+        } catch (FactoryException e) {
+            Context.warningOccured(Context.current(), DefaultOperationMethod.class, "setDescriptors", e, true);
+        }
+        final Map<String,?> properties = Collections.singletonMap(ParameterDescriptorGroup.NAME_KEY, name);
+        if (method != null) {
+            /*
+             * Verify that the pre-defined operation method contains at least all the parameters specified by
+             * the 'descriptors' array. If this is the case, then the pre-defined parameters will be used in
+             * replacement of the given ones.
+             */
+            final ParameterDescriptorGroup parameters = method.getParameters();
+            return CC_GeneralOperationParameter.merge(properties,
+                    IdentifiedObjects.getProperties(parameters),
+                    1, 1, descriptors, parameters, true);
+        }
+        return new DefaultParameterDescriptorGroup(properties, 1, 1, descriptors);
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameterGroup.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameterGroup.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameterGroup.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_OperationParameterGroup.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -16,10 +16,18 @@
  */
 package org.apache.sis.internal.jaxb.referencing;
 
+import java.util.Map;
+import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.ConcurrentModificationException;
 import javax.xml.bind.annotation.XmlElement;
+import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.GeneralParameterDescriptor;
 import org.apache.sis.internal.jaxb.gco.PropertyType;
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
+import org.apache.sis.util.collection.Containers;
+import org.apache.sis.util.resources.Errors;
 
 
 /**
@@ -89,4 +97,105 @@ public final class CC_OperationParameter
     public void setElement(final DefaultParameterDescriptorGroup parameter) {
         metadata = parameter;
     }
+
+    /**
+     * Invoked by {@link DefaultParameterDescriptorGroup#setDescriptors(GeneralParameterDescriptor[])}
+     * for merging into a single set the descriptors which are repeated twice in a GML document.
+     * The descriptors are:
+     *
+     * <ol>
+     *   <li>The descriptors declared explicitely in the descriptor group.</li>
+     *   <li>The descriptors declared in the parameter values.</li>
+     * </ol>
+     *
+     * The later are more complete than the former, because they allow us to infer the {@code valueClass} property.
+     *
+     * <div class="note"><b>Note:</b>
+     * this code is defined in this {@code CC_OperationParameterGroup} class instead than in the
+     * {@link DefaultParameterDescriptorGroup} class in the hope to reduce the amount of code
+     * processed by the JVM in the common case where JAXB (un)marshalling is not needed.</div>
+     *
+     * @param  descriptors The descriptors declared in the {@code ParameterDescriptorGroup}.
+     * @param  parameters  The descriptors declared in the {@code ParameterValue}.
+     * @return A single set containing the two given set of parameters.
+     */
+    public static GeneralParameterDescriptor[] merge(final List<GeneralParameterDescriptor> descriptors,
+            final GeneralParameterDescriptor[] parameters)
+    {
+        if (descriptors.isEmpty()) {
+            return parameters;
+        }
+        final Map<String,GeneralParameterDescriptor> union =
+                new LinkedHashMap<>(Containers.hashMapCapacity(descriptors.size()));
+        /*
+         * Collect the descriptors declared explicitely in the ParameterDescriptorGroup. We should never have
+         * two descriptors of the same name since the DefaultParameterDescriptorGroup constructor checked for
+         * name ambiguity. If a name collision is nevertheless detected, this would mean that a descriptor's
+         * name mutated.
+         */
+        for (final GeneralParameterDescriptor p : descriptors) {
+            final String name = p.getName().getCode();
+            if (union.put(name, p) != null) {
+                throw new ConcurrentModificationException(Errors.format(Errors.Keys.UnexpectedChange_1, name));
+            }
+        }
+        /*
+         * Verify if any descriptors found in the ParameterValue instances could replace the current descriptors.
+         * We give precedence to the descriptors having a non-null 'valueClass' property, which normally are the
+         * descriptors from the 'parameters' array.
+         */
+        for (GeneralParameterDescriptor replacement : parameters) {
+            final String name = replacement.getName().getCode();
+            GeneralParameterDescriptor previous = union.put(name, replacement);
+            if (previous != null) {
+                if (previous instanceof ParameterDescriptor<?>) {
+                    verifyEquivalence(name, replacement instanceof ParameterDescriptor<?>);
+                    final Class<?> valueClass = ((ParameterDescriptor<?>) previous).getValueClass();
+                    if (valueClass != null) {
+                        final Class<?> r = ((ParameterDescriptor<?>) replacement).getValueClass();
+                        if (r != null) {
+                            /*
+                             * Should never happen unless the same (according its name) ParameterValue appears
+                             * more than once in the 'parameters' array, or unless this method is invoked more
+                             * often than expected.
+                             */
+                            verifyEquivalence(name, valueClass == r);
+                        } else {
+                            /*
+                             * Should never happen unless JAXB unmarshalled the elements in reverse order
+                             * (i.e. ParameterValue before ParameterDescriptorGroup). Since this behavior
+                             * may depend on JAXB implementation, we are better to check for such case.
+                             * Restore the previous value in the map and swap 'previous' with 'replacement'.
+                             */
+                            previous = union.put(name, replacement = previous);
+                        }
+                    }
+                } else if (previous instanceof ParameterDescriptorGroup) {
+                    verifyEquivalence(name, replacement instanceof ParameterDescriptorGroup);
+                }
+                /*
+                 * Verify that the replacement contains at least all the information provided by the previous
+                 * descriptor. The replacement is allowed to contain more information however.
+                 */
+                final GeneralParameterDescriptor r = CC_GeneralOperationParameter.replacement(previous, replacement);
+                if (r != replacement) {
+                    union.put(name, r);
+
+                    // TODO: We should instead update DefaultParameterValue descriptor here.
+                    verifyEquivalence(name, false);
+                }
+            }
+        }
+        return union.values().toArray(new GeneralParameterDescriptor[union.size()]);
+    }
+
+    /**
+     * Throws an exception for mismatched descriptor if a condition is false.
+     * This is used for verifying that a descriptors has the expected properties.
+     */
+    private static void verifyEquivalence(final String name, final boolean condition) {
+        if (!condition) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedParameterDescriptor_1, name));
+        }
+    }
 }

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=1700283&r1=1700282&r2=1700283&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] Mon Aug 31 17:52:00 2015
@@ -34,6 +34,7 @@ import org.apache.sis.util.ComparisonMod
 import org.apache.sis.util.Debug;
 
 import static org.apache.sis.util.Utilities.deepEquals;
+import static org.apache.sis.internal.jaxb.referencing.CC_GeneralOperationParameter.DEFAULT_OCCURRENCE;
 
 // Branch-dependent imports
 import java.util.Objects;
@@ -140,8 +141,8 @@ public abstract class AbstractParameterD
      */
     AbstractParameterDescriptor() {
         super(org.apache.sis.internal.referencing.NilReferencingObject.INSTANCE);
-        minimumOccurs = 1;  // Default value is XML element is omitted.
-        maximumOccurs = 1;
+        minimumOccurs = DEFAULT_OCCURRENCE;  // Default value if XML element is omitted.
+        maximumOccurs = DEFAULT_OCCURRENCE;
     }
 
     /**
@@ -378,7 +379,7 @@ public abstract class AbstractParameterD
     @XmlSchemaType(name = "nonNegativeInteger")
     private Integer getNonDefaultMinimumOccurs() {
         final int n = getMinimumOccurs();
-        return (n != 1) ? n : null;
+        return (n != DEFAULT_OCCURRENCE) ? n : null;
     }
 
     /**
@@ -395,20 +396,20 @@ public abstract class AbstractParameterD
     @XmlSchemaType(name = "nonNegativeInteger")
     private Integer getNonDefaultMaximumOccurs() {
         final int n = getMaximumOccurs();
-        return (n != 1) ? n : null;
+        return (n != DEFAULT_OCCURRENCE) ? n : null;
     }
 
     /**
      * Invoked by JAXB for unmarshalling the {@link #minimumOccurs} value.
      */
     private void setNonDefaultMinimumOccurs(final Integer n) {
-        minimumOccurs = (n != null) ? crop(n) : 1;
+        minimumOccurs = (n != null) ? crop(n) : DEFAULT_OCCURRENCE;
     }
 
     /**
      * Invoked by JAXB for unmarshalling the {@link #maximumOccurs} value.
      */
     private void setNonDefaultMaximumOccurs(final Integer n) {
-        maximumOccurs = (n != null) ? crop(n) : 1;
+        maximumOccurs = (n != null) ? crop(n) : DEFAULT_OCCURRENCE;
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptorGroup.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptorGroup.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptorGroup.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptorGroup.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -21,7 +21,6 @@ import java.util.Set;
 import java.util.List;
 import java.util.HashSet;
 import java.util.Collections;
-import java.util.LinkedHashMap;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -31,9 +30,9 @@ import org.opengis.parameter.ParameterDe
 import org.opengis.parameter.GeneralParameterDescriptor;
 import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.parameter.InvalidParameterNameException;
+import org.apache.sis.internal.jaxb.referencing.CC_OperationParameterGroup;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ComparisonMode;
@@ -111,10 +110,12 @@ public class DefaultParameterDescriptorG
 
     /**
      * Constructs a new object in which every attributes are set to a null value or an empty list.
-     * <strong>This is not a valid object.</strong> This constructor is strictly reserved to JAXB,
-     * which will assign values to the fields using reflexion.
+     * <strong>This is not a valid object.</strong> This constructor is strictly reserved to JAXB
+     * and to {@link DefaultParameterValueGroup}, which will assign values later.
+     *
+     * @see #setDescriptors(GeneralParameterDescriptor[])
      */
-    private DefaultParameterDescriptorGroup() {
+    DefaultParameterDescriptorGroup() {
         descriptors = Collections.emptyList();
     }
 
@@ -432,7 +433,7 @@ public class DefaultParameterDescriptorG
 
     /**
      * Invoked by JAXB or by {@link DefaultParameterValueGroup} for setting the unmarshalled parameters.
-     * If parameters already exist, them this method computes the union of the two parameter collections
+     * If parameters already exist, then this method computes the union of the two parameter collections
      * with the new parameters having precedence over the old ones.
      *
      * <div class="note"><b>Rational:</b>
@@ -448,18 +449,8 @@ public class DefaultParameterDescriptorG
      * </div>
      */
     final void setDescriptors(GeneralParameterDescriptor[] parameters) {
+        parameters = CC_OperationParameterGroup.merge(descriptors, parameters);
         verifyNames(null, parameters);
-        if (!descriptors.isEmpty()) {
-            final Map<String,GeneralParameterDescriptor> union =
-                    new LinkedHashMap<>(Containers.hashMapCapacity(descriptors.size()));
-            for (final GeneralParameterDescriptor p : descriptors) {
-                union.put(p.getName().getCode(), p);
-            }
-            for (final GeneralParameterDescriptor p : parameters) {
-                union.put(p.getName().getCode(), p);
-            }
-            parameters = union.values().toArray(new GeneralParameterDescriptor[union.size()]);
-        }
         descriptors = asList(parameters);
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValueGroup.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValueGroup.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValueGroup.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValueGroup.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -519,7 +519,7 @@ public class DefaultParameterValueGroup
      * Invoked by JAXB for setting the unmarshalled parameters. This method should be invoked last
      * (after {@link #setDescriptor(ParameterDescriptorGroup)}) even if the {@code parameterValue}
      * elements were first in the XML document. This is the case at least with the JAXB reference
-     * implementation.
+     * implementation, because the property type is an array (it would not work with a list).
      */
     private void setValues(final GeneralParameterValue[] parameters) {
         final GeneralParameterDescriptor[] descriptors = new GeneralParameterDescriptor[parameters.length];
@@ -528,13 +528,12 @@ public class DefaultParameterValueGroup
         }
         if (values == null) {
             // Should never happen, unless the XML document is invalid and does not have a 'group' element.
-            
-        } else {
-            // We known that the descriptor is an instance of our DefaultParameterDescriptorGroup
-            // implementation because this is what we declare to the JAXBContext and in adapters.
-            ((DefaultParameterDescriptorGroup) values.descriptor).setDescriptors(descriptors);
-            values.clear();  // Because references to parameter descriptors have changed.
+            values = new ParameterValueList(new DefaultParameterDescriptorGroup());
         }
+        // We known that the descriptor is an instance of our DefaultParameterDescriptorGroup
+        // implementation because this is what we declare to the JAXBContext and in adapters.
+        ((DefaultParameterDescriptorGroup) values.descriptor).setDescriptors(descriptors);
+        values.clear();  // Because references to parameter descriptors have changed.
         values.addAll(Arrays.asList(parameters));
     }
 

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -17,21 +17,26 @@
 package org.apache.sis.referencing.operation;
 
 import java.util.Map;
+import java.util.List;
+import java.util.Arrays;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.GeneralParameterValue;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.SingleOperation;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.parameter.Parameterized;
+import org.apache.sis.parameter.DefaultParameterValueGroup;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.operation.transform.PassThroughTransform;
+import org.apache.sis.internal.jaxb.referencing.CC_OperationMethod;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.util.Constants;
@@ -57,7 +62,7 @@ import java.util.Objects;
  */
 @XmlType(name="AbstractSingleOperationType", propOrder = {
     "method",
-//  "parameters"
+    "parameters"
 })
 @XmlRootElement(name = "AbstractSingleOperation")
 @XmlSeeAlso({
@@ -77,8 +82,11 @@ class AbstractSingleOperation extends Ab
 
     /**
      * The parameter values, or {@code null} for inferring it from the math transform.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link #setParameters(GeneralParameterValue[])}</p>
      */
-    private final ParameterValueGroup parameters;
+    private ParameterValueGroup parameters;
 
     /**
      * Constructs a new object in which every attributes are set to a null value.
@@ -87,7 +95,6 @@ class AbstractSingleOperation extends Ab
      */
     AbstractSingleOperation() {
         method = null;
-        parameters = null;
     }
 
     /**
@@ -406,4 +413,49 @@ class AbstractSingleOperation extends Ab
          */
         return true;
     }
+
+    // ---- XML SUPPORT ----------------------------------------------------
+
+    /**
+     * Invoked by JAXB for getting the parameters to marshal. This method usually marshals the sequence
+     * of parameters without their {@link ParameterValueGroup} wrapper, because GML is defined that way.
+     * The {@code ParameterValueGroup} wrapper is a GeoAPI addition done for allowing usage of its
+     * methods as a convenience (e.g. {@link ParameterValueGroup#parameter(String)}).
+     *
+     * <p>However it could happen that the user really wanted to specify a {@code ParameterValueGroup} as the
+     * sole {@code <gml:parameterValue>} element. We currently have no easy way to distinguish those cases.
+     * See {@link DefaultOperationMethod#getDescriptors()} for more discussion.</p>
+     *
+     * @see DefaultOperationMethod#getDescriptors()
+     */
+    @XmlElement(name = "parameterValue")
+    private GeneralParameterValue[] getParameters() {
+        if (parameters != null) {
+            final List<GeneralParameterValue> values = parameters.values();
+            if (values != null) {      // Paranoiac check (should not be allowed).
+                return CC_OperationMethod.filterImplicit(values.toArray(new GeneralParameterValue[values.size()]));
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Invoked by JAXB for setting the unmarshalled parameters.
+     * This method wraps the given parameters in a {@link ParameterValueGroup},
+     * unless the given descriptors was already a {@code ParameterValueGroup}.
+     *
+     * @see DefaultOperationMethod#setDescriptors
+     */
+    private void setParameters(final GeneralParameterValue[] values) {
+        if (ReferencingUtilities.canSetProperty(DefaultOperationMethod.class,
+                "setParameters", "parameterValue", parameters != null))
+        {
+            ParameterDescriptorGroup descriptor = method.getParameters();
+            parameters = new DefaultParameterValueGroup(descriptor);
+            parameters.values().addAll(Arrays.asList(values));
+            if (method instanceof DefaultOperationMethod) {
+                ((DefaultOperationMethod) method).setParameters(parameters.getDescriptor());
+            }
+        }
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -43,6 +43,7 @@ import org.apache.sis.util.iso.SimpleInt
 import org.apache.sis.internal.util.Citations;
 import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.internal.jaxb.gco.StringAdapter;
+import org.apache.sis.internal.jaxb.referencing.CC_OperationMethod;
 import org.apache.sis.internal.referencing.NilReferencingObject;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
@@ -590,7 +591,8 @@ public class DefaultOperationMethod exte
      *
      * <div class="note"><b>Departure from the ISO 19111 standard:</b>
      * this property is mandatory according ISO 19111, but may be null in Apache SIS if the
-     * {@link #DefaultOperationMethod(MathTransform)} constructor has been unable to infer it.</div>
+     * {@link #DefaultOperationMethod(MathTransform)} constructor has been unable to infer it
+     * or if this {@code OperationMethod} has been read from an incomplete GML document.</div>
      *
      * @return The parameters, or {@code null} if unknown.
      *
@@ -783,13 +785,17 @@ public class DefaultOperationMethod exte
      *
      * But we would need to make sure that {@link AbstractSingleOperation#getParameters()} is consistent
      * with the decision taken by this method.</div>
+     *
+     * @see #getParameters()
+     * @see AbstractSingleOperation#getParameters()
      */
     @XmlElement(name = "parameter")
     private GeneralParameterDescriptor[] getDescriptors() {
         if (parameters != null) {
             final List<GeneralParameterDescriptor> descriptors = parameters.descriptors();
             if (descriptors != null) {      // Paranoiac check (should not be allowed).
-                return descriptors.toArray(new GeneralParameterDescriptor[descriptors.size()]);
+                return CC_OperationMethod.filterImplicit(descriptors.toArray(
+                        new GeneralParameterDescriptor[descriptors.size()]));
             }
         }
         return null;
@@ -797,22 +803,29 @@ public class DefaultOperationMethod exte
 
     /**
      * Invoked by JAXB for setting the unmarshalled parameters.
-     * This method wraps the given descriptors in an {@link DefaultParameterDescriptorGroup},
-     * unless the given descriptors was already a {@code ParameterDescriptorGroup}.
+     * This method wraps the given descriptors in a {@link DefaultParameterDescriptorGroup}.
+     *
+     * <p>The parameter descriptors created by this method are incomplete since we can not
+     * provide a non-null value for {@link ParameterDescriptor#getValueClass()}. The value
+     * class will be provided either by replacing this {@code OperationMethod} by one of the
+     * pre-defined methods, or by unmarshalling the enclosing {@link AbstractSingleOperation}.</p>
      *
-     * <p>The parameter descriptors created by this method are incomplete, since they can not
-     * provide a non-null value for {@link ParameterDescriptor#getValueClass()}.</p>
+     * @see AbstractSingleOperation#setParameters
      */
     private void setDescriptors(final GeneralParameterDescriptor[] descriptors) {
         if (ReferencingUtilities.canSetProperty(DefaultOperationMethod.class,
                 "setDescriptors", "parameter", parameters != null))
         {
-            if (descriptors.length == 1 && descriptors[0] instanceof ParameterDescriptorGroup) {
-                parameters = (ParameterDescriptorGroup) descriptors[0];
-            } else {
-                parameters = new DefaultParameterDescriptorGroup(
-                        Collections.singletonMap(NAME_KEY, super.getName()), 1, 1, descriptors);
-            }
+            parameters = CC_OperationMethod.group(super.getName(), descriptors);
         }
     }
+
+    /**
+     * Invoked by {@link AbstractSingleOperation} for completing the parameter descriptor.
+     *
+     * @see #getParameters()
+     */
+    final void setParameters(final ParameterDescriptorGroup descriptor) {
+        parameters = descriptor;
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -68,6 +68,7 @@
     @XmlJavaTypeAdapter(CI_Citation.class),
     @XmlJavaTypeAdapter(DQ_PositionalAccuracy.class),
     @XmlJavaTypeAdapter(CC_OperationMethod.class),
+    @XmlJavaTypeAdapter(CC_GeneralParameterValue.class),
     @XmlJavaTypeAdapter(CC_GeneralOperationParameter.class),
     @XmlJavaTypeAdapter(InternationalStringConverter.class)
 })

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterValueGroupWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterValueGroupWrapper.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterValueGroupWrapper.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterValueGroupWrapper.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -33,6 +33,7 @@ import org.opengis.parameter.ParameterDe
  * @version 0.4
  * @module
  */
+@SuppressWarnings("CloneInNonCloneableClass")
 final class ParameterValueGroupWrapper implements ParameterValueGroup {
     /**
      * The implementation to hide.
@@ -46,10 +47,11 @@ final class ParameterValueGroupWrapper i
         this.impl = impl;
     }
 
+    @SuppressWarnings("CloneDoesntCallSuperClone")
+    @Override public ParameterValueGroup         clone()                {return impl.clone();}
     @Override public ParameterDescriptorGroup    getDescriptor()        {return impl.getDescriptor();}
     @Override public List<GeneralParameterValue> values()               {return impl.values();}
     @Override public ParameterValue<?>           parameter(String name) {return impl.parameter(name);}
     @Override public List<ParameterValueGroup>   groups(String name)    {return impl.groups(name);}
     @Override public ParameterValueGroup         addGroup(String name)  {return impl.addGroup(name);}
-    @Override public ParameterValueGroup         clone()                {return impl.clone();}
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/OperationMarshallingTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/OperationMarshallingTest.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/OperationMarshallingTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/OperationMarshallingTest.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -19,11 +19,11 @@ package org.apache.sis.referencing.opera
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Iterator;
-import org.opengis.parameter.GeneralParameterDescriptor;
 import javax.xml.bind.JAXBException;
 import javax.measure.unit.NonSI;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.GeneralParameterDescriptor;
 import org.apache.sis.parameter.ParameterBuilder;
 import org.apache.sis.xml.Namespaces;
 import org.apache.sis.xml.XML;
@@ -55,8 +55,8 @@ public final strictfp class OperationMar
         final ParameterBuilder builder = new ParameterBuilder();
         builder.setCodeSpace(EPSG, "EPSG").setRequired(true);
         ParameterDescriptor<?>[] parameters = {
-            builder.addName("Latitude of natural origin" ).create(0, NonSI.DEGREE_ANGLE),
-            builder.addName("Longitude of natural origin").create(0, NonSI.DEGREE_ANGLE)
+            builder.addIdentifier("8801").addName("Latitude of natural origin" ).create(0, NonSI.DEGREE_ANGLE),
+            builder.addIdentifier("8802").addName("Longitude of natural origin").create(0, NonSI.DEGREE_ANGLE)
             // There is more parameters for a Mercator projection, but 2 is enough for this test.
         };
         builder.addName(null, "Mercator");
@@ -81,12 +81,14 @@ public final strictfp class OperationMar
                       + "  <gml:sourceDimensions>2</gml:sourceDimensions>\n"
                       + "  <gml:targetDimensions>2</gml:targetDimensions>\n"
                       + "  <gml:parameter>\n"
-                      + "    <gml:OperationParameter gml:id=\"LatitudeOfNaturalOrigin\">\n"
+                      + "    <gml:OperationParameter gml:id=\"epsg-parameter-8801\">\n"
+                      + "      <gml:identifier codeSpace=\"IOGP\">urn:ogc:def:parameter:EPSG::8801</gml:identifier>\n"
                       + "      <gml:name codeSpace=\"EPSG\">Latitude of natural origin</gml:name>\n"
                       + "    </gml:OperationParameter>\n"
                       + "  </gml:parameter>\n"
                       + "  <gml:parameter>\n"
-                      + "    <gml:OperationParameter gml:id=\"LongitudeOfNaturalOrigin\">\n"
+                      + "    <gml:OperationParameter gml:id=\"epsg-parameter-8802\">\n"
+                      + "      <gml:identifier codeSpace=\"IOGP\">urn:ogc:def:parameter:EPSG::8802</gml:identifier>\n"
                       + "      <gml:name codeSpace=\"EPSG\">Longitude of natural origin</gml:name>\n"
                       + "    </gml:OperationParameter>\n"
                       + "  </gml:parameter>\n"
@@ -104,7 +106,7 @@ public final strictfp class OperationMar
         assertEquals("sourceDimensions", Integer.valueOf(2), method.getSourceDimensions());
         assertEquals("targetDimensions", Integer.valueOf(2), method.getTargetDimensions());
         final ParameterDescriptorGroup parameters = method.getParameters();
-        assertEquals("parameters.name", method.getName(), parameters.getName());
+        assertEquals("parameters.name", "Mercator", parameters.getName().getCode());
         final Iterator<GeneralParameterDescriptor> it = parameters.descriptors().iterator();
         verifyIncompleteDescriptor("Latitude of natural origin",  it.next());
         verifyIncompleteDescriptor("Longitude of natural origin", it.next());
@@ -122,6 +124,5 @@ public final strictfp class OperationMar
     private static void verifyIncompleteDescriptor(final String name, final GeneralParameterDescriptor descriptor) {
         assertIdentifierEquals("name", "##unrestricted", "EPSG", null, name, descriptor.getName());
         assertEquals("maximumOccurs", 1, descriptor.getMaximumOccurs());
-        assertEquals("minimumOccurs", 1, descriptor.getMinimumOccurs());
     }
 }

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=1700283&r1=1700282&r2=1700283&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] Mon Aug 31 17:52:00 2015
@@ -46,7 +46,7 @@ import org.apache.sis.xml.ReferenceResol
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.6
  * @module
  */
 public final class Context extends MarshalContext {
@@ -530,16 +530,16 @@ public final class Context extends Marsh
      * Convenience method for sending a warning for the given exception.
      * The logger will be {@code "org.apache.sis.xml"}.
      *
-     * @param context The current context, or {@code null} if none.
-     * @param classe  The class to declare as the warning source.
-     * @param method  The name of the method to declare as the warning source.
-     * @param cause   The exception which occurred.
-     * @param warning {@code true} for {@link Level#WARNING}, or {@code false} for {@link Level#FINE}.
+     * @param context   The current context, or {@code null} if none.
+     * @param classe    The class to declare as the warning source.
+     * @param method    The name of the method to declare as the warning source.
+     * @param cause     The exception which occurred.
+     * @param isWarning {@code true} for {@link Level#WARNING}, or {@code false} for {@link Level#FINE}.
      */
     public static void warningOccured(final Context context, final Class<?> classe,
-            final String method, final Exception cause, final boolean warning)
+            final String method, final Exception cause, final boolean isWarning)
     {
-        warningOccured(context, warning ? Level.WARNING : Level.FINE, classe, method, cause,
+        warningOccured(context, isWarning ? Level.WARNING : Level.FINE, classe, method, cause,
                 null, (short) 0, (Object[]) null);
     }
 

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -20,6 +20,7 @@ import java.util.*;
 import java.lang.reflect.Array;
 import org.opengis.util.CodeList;
 import org.apache.sis.util.Static;
+import org.apache.sis.util.Numbers;
 import org.apache.sis.util.collection.CodeListSet;
 import org.apache.sis.util.resources.Errors;
 import org.opengis.parameter.InvalidParameterCardinalityException;
@@ -588,6 +589,27 @@ public final class CollectionsExt extend
     }
 
     /**
+     * Returns the elements of the given collection as an array. This method can be used when the {@code valueClass}
+     * argument is not known at compile-time. If the {@code valueClass} is known at compile-time, then callers should
+     * use {@link Collection#toArray(T[])} instead.
+     *
+     * @param  <T>        The compile-time value of {@code valueClass}.
+     * @param  collection The collection from which to get the elements.
+     * @param  valueClass The runtime type of collection elements.
+     * @return The collection elements as an array, or {@code null} if {@code collection} is null.
+     *
+     * @since 0.6
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T[] toArray(final Collection<T> collection, final Class<T> valueClass) {
+        assert Numbers.primitiveToWrapper(valueClass) == valueClass : valueClass;
+        if (collection != null) {
+            return collection.toArray((T[]) Array.newInstance(valueClass, collection.size()));
+        }
+        return null;
+    }
+
+    /**
      * Adds a value in a pseudo multi-values map. The multi-values map is simulated by a map of lists.
      * The map can be initially empty - lists will be created as needed.
      *

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/CollectionsExtTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/CollectionsExtTest.java?rev=1700283&r1=1700282&r2=1700283&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/CollectionsExtTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/CollectionsExtTest.java [UTF-8] Mon Aug 31 17:52:00 2015
@@ -44,7 +44,7 @@ import java.util.function.Function;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.6
  * @module
  */
 public final strictfp class CollectionsExtTest extends TestCase {
@@ -153,4 +153,16 @@ public final strictfp class CollectionsE
         assertFalse(CollectionsExt.identityEquals(c2.iterator(), c1.iterator()));
         assertTrue(CollectionsExt.identityEquals(c1.iterator(), Arrays.asList("A", "B", "C").iterator()));
     }
+
+    /**
+     * Tests {@link CollectionsExt#toArray(Collection, Class)}.
+     *
+     * @since 0.6
+     */
+    @Test
+    public void testToArray() {
+        final String[] expected = new String[] {"One", "Two", "Three"};
+        final String[] actual = CollectionsExt.toArray(Arrays.asList(expected), String.class);
+        assertArrayEquals(expected, actual);
+    }
 }



Mime
View raw message