This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 0d58e3a7b4 Remove `DefaultParameter` (the implementation of ISO 19157 
`DQM_Parameter`). This is replaced by a retrofitting in `ParameterDescriptor` 
for a unified API.
0d58e3a7b4 is described below

commit 0d58e3a7b497be64b4faf2181623b9990737639f
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Nov 16 19:12:40 2022 +0100

    Remove `DefaultParameter` (the implementation of ISO 19157 `DQM_Parameter`).
    This is replaced by a retrofitting in `ParameterDescriptor` for a unified 
API.
    
    https://github.com/opengeospatial/geoapi/issues/74
---
 .../sis/internal/jaxb/metadata/DQM_Parameter.java  |  27 +--
 .../internal/jaxb/metadata/replace/Parameter.java  | 173 ++++++++++++++
 .../jaxb/metadata/replace/QualityParameter.java    | 245 ++++++++++++++++++++
 .../jaxb/metadata/replace/ServiceParameter.java    | 231 ++++++++-----------
 .../jaxb/metadata/replace/package-info.java        |  21 +-
 .../sis/internal/metadata/ReferencingServices.java |   5 +-
 .../sis/metadata/iso/quality/DefaultMeasure.java   |  18 +-
 .../sis/metadata/iso/quality/DefaultParameter.java | 252 ---------------------
 .../metadata/replace/QualityParameterTest.java     | 117 ++++++++++
 .../metadata/replace/ServiceParameterTest.java     |  14 +-
 .../apache/sis/metadata/iso/AllMetadataTest.java   |   1 -
 .../DefaultServiceIdentificationTest.java          |   8 +-
 .../apache/sis/test/suite/MetadataTestSuite.java   |   1 +
 .../metadata/xml/2007/ServiceIdentification.xml    |   2 +-
 .../metadata/xml/2016/ServiceIdentification.xml    |   4 +-
 .../internal/referencing/ServicesForMetadata.java  |   5 +-
 .../sis/parameter/DefaultParameterDescriptor.java  |  28 ++-
 17 files changed, 701 insertions(+), 451 deletions(-)

diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/DQM_Parameter.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/DQM_Parameter.java
index ba308a6b39..fe1fb38c8d 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/DQM_Parameter.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/DQM_Parameter.java
@@ -17,9 +17,9 @@
 package org.apache.sis.internal.jaxb.metadata;
 
 import javax.xml.bind.annotation.XmlElementRef;
-import org.opengis.metadata.quality.Parameter;
-import org.apache.sis.metadata.iso.quality.DefaultParameter;
+import org.opengis.parameter.ParameterDescriptor;
 import org.apache.sis.internal.jaxb.gco.PropertyType;
+import org.apache.sis.internal.jaxb.metadata.replace.QualityParameter;
 
 
 /**
@@ -31,7 +31,7 @@ import org.apache.sis.internal.jaxb.gco.PropertyType;
  * @since   1.3
  * @module
  */
-public final class DQM_Parameter extends PropertyType<DQM_Parameter, 
Parameter> {
+public final class DQM_Parameter extends PropertyType<DQM_Parameter, 
ParameterDescriptor<?>> {
     /**
      * Empty constructor for JAXB only.
      */
@@ -43,17 +43,18 @@ public final class DQM_Parameter extends 
PropertyType<DQM_Parameter, Parameter>
      * This method is indirectly invoked by the private constructor
      * below, so it shall not depend on the state of this object.
      *
-     * @return {@code Parameter.class}
+     * @return {@code ParameterDescriptor.class}
      */
     @Override
-    protected Class<Parameter> getBoundType() {
-        return Parameter.class;
+    @SuppressWarnings("unchecked")
+    protected Class<ParameterDescriptor<?>> getBoundType() {
+        return (Class) ParameterDescriptor.class;
     }
 
     /**
      * Constructor for the {@link #wrap} method only.
      */
-    private DQM_Parameter(final Parameter metadata) {
+    private DQM_Parameter(final ParameterDescriptor<?> metadata) {
         super(metadata);
     }
 
@@ -65,7 +66,7 @@ public final class DQM_Parameter extends 
PropertyType<DQM_Parameter, Parameter>
      * @return a {@code PropertyType} wrapping the given the metadata element.
      */
     @Override
-    protected DQM_Parameter wrap(final Parameter metadata) {
+    protected DQM_Parameter wrap(final ParameterDescriptor<?> metadata) {
         return new DQM_Parameter(metadata);
     }
 
@@ -77,16 +78,16 @@ public final class DQM_Parameter extends 
PropertyType<DQM_Parameter, Parameter>
      * @return the metadata to be marshalled.
      */
     @XmlElementRef
-    public DefaultParameter getElement() {
-        return DefaultParameter.castOrCopy(metadata);
+    public QualityParameter getElement() {
+        return QualityParameter.castOrCopy(metadata);
     }
 
     /**
      * Invoked by JAXB at unmarshalling time for storing the result 
temporarily.
      *
-     * @param  metadata  the unmarshalled metadata.
+     * @param  value  the unmarshalled metadata.
      */
-    public void setElement(final DefaultParameter metadata) {
-        this.metadata = metadata;
+    public void setElement(final QualityParameter value) {
+        metadata = value;
     }
 }
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/Parameter.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/Parameter.java
new file mode 100644
index 0000000000..7d1235839a
--- /dev/null
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/Parameter.java
@@ -0,0 +1,173 @@
+/*
+ * 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.metadata.replace;
+
+import java.util.Objects;
+import org.opengis.util.TypeName;
+import org.opengis.metadata.Identifier;
+import org.opengis.parameter.ParameterValue;
+import org.opengis.parameter.ParameterDescriptor;
+import org.apache.sis.internal.simple.SimpleIdentifiedObject;
+import org.apache.sis.internal.metadata.ReferencingServices;
+import org.apache.sis.util.ComparisonMode;
+
+import static org.apache.sis.util.Utilities.deepEquals;
+
+
+/**
+ * Base class for ISO/OGC parameter classes replaced by {@code 
ParameterDescriptor} in GeoAPI.
+ * GeoAPI tries to provides a single API for the parameter classes defined in 
various specifications
+ * (ISO 19111, ISO 19115, ISO 19157, Web Processing Service).
+ * But we still need separated representations at XML (un)marshalling time.
+ *
+ * <p>Note that this implementation is simple and serves no other purpose than 
being a container for XML
+ * parsing and formatting. For real parameter framework, consider using {@link 
org.apache.sis.parameter}
+ * package instead.</p>
+ *
+ * @param  <T>  the type of parameter values.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since   1.3
+ * @module
+ */
+abstract class Parameter<T> extends SimpleIdentifiedObject implements 
ParameterDescriptor<T> {
+    /**
+     * A copy of {@code this} as a fully-implemented parameter descriptor.
+     * This is created when first needed for implementation of {@link 
#createValue()}.
+     * Should not be created for other purposes — in particular for 
implementation of getter methods —
+     * because it would create an infinite loop in {@code 
DefaultParameterDescriptor} copy constructor.
+     */
+    private transient volatile ParameterDescriptor<T> descriptor;
+
+    /**
+     * Creates an initially empty parameter.
+     * This constructor is needed by JAXB at unmarshalling time.
+     */
+    Parameter() {
+    }
+
+    /**
+     * Creates a parameter with the values of the given descriptor.
+     * This is used at marshalling time for converting a generic descriptor
+     * to the standard-specific parameter representation defined by subclass.
+     *
+     * @param  parameter  the parameter to marshal.
+     */
+    Parameter(final ParameterDescriptor<T> parameter) {
+        super(parameter);
+        descriptor = parameter;
+    }
+
+    /**
+     * Returns the name that describes the type of parameter values.
+     * The default implementation returns a non-null value only if this class 
is wrapping
+     * another parameter descriptor. Subclasses should override this method 
for computing
+     * a type name if this method returns null.
+     *
+     * @return the type name of value component(s) in this parameter, or 
{@code null} if unknown.
+     */
+    @Override
+    public TypeName getValueType() {
+        final ParameterDescriptor<T> p = descriptor;
+        return (p != null) ? p.getValueType() : null;
+    }
+
+    /**
+     * Returns the class that describes the type of parameter values.
+     * The default implementation returns a non-null value only if this class 
is wrapping
+     * another parameter descriptor. Subclasses should override this method 
for computing
+     * a class if this method returns null.
+     *
+     * @return the value class inferred from the attribute type, or {@code 
null} if unknown.
+     */
+    @Override
+    public Class<T> getValueClass() {
+        final ParameterDescriptor<T> p = descriptor;
+        return (p != null) ? p.getValueClass() : null;
+    }
+
+    /**
+     * Creates a new instance of {@code ParameterValue}.
+     * This method delegates the work to {@link 
org.apache.sis.parameter.DefaultParameterDescriptor}
+     * since this {@code ServiceParameter} class is not a full-featured 
parameter descriptor implementation.
+     *
+     * @return a new instance of {@code ParameterValue}.
+     */
+    @Override
+    public final ParameterValue<T> createValue() {
+        ParameterDescriptor<T> p;
+        synchronized (this) {
+            p = descriptor;
+            if (p == null) {
+                descriptor = p = 
ReferencingServices.getInstance().toImplementation(this);
+            }
+        }
+        return p.createValue();
+    }
+
+    /*
+     * Do not override getValidValues(), getMinimumValue(), getMaximumValue(), 
getDefaultValue() or getUnit()
+     * in order to keep property values stable before and after the 
`descriptor` field has been initialized.
+     * The `equals(Object)` method assumes that all those methods return null.
+     */
+
+    /**
+     * Compares this object with the given one for equality. This 
implementation should be consistent
+     * with {@link 
org.apache.sis.parameter.DefaultParameterDescriptor#equals(Object)} 
implementation,
+     * with the simplification that some {@code Parameter} property values are 
always null.
+     *
+     * @param  object  the object to compare with this reference system.
+     * @param  mode    the strictness level of the comparison.
+     * @return {@code true} if both objects are equal.
+     */
+    @Override
+    public final boolean equals(final Object object, final ComparisonMode 
mode) {
+        if (object == this) {
+            return true;
+        }
+        if (super.equals(object, mode) && object instanceof 
ParameterDescriptor<?>) {
+            final ParameterDescriptor<?> that = (ParameterDescriptor<?>) 
object;
+            if (that.getUnit()         == null &&
+                that.getDefaultValue() == null &&
+                that.getValueClass()   == getValueClass())
+            {
+                if (mode.isIgnoringMetadata()) {
+                    return Objects.equals(toString(getName()), 
toString(that.getName()));
+                    // super.equals(…) already compared `getName()` in other 
modes.
+                }
+                return deepEquals(that.getValueType(),   getValueType(),   
mode) &&
+                       deepEquals(that.getDescription(), getDescription(), 
mode) &&
+                                  that.getDirection()     == getDirection()    
 &&
+                                  that.getMinimumOccurs() == 
getMinimumOccurs() &&
+                                  that.getMaximumOccurs() == 
getMaximumOccurs() &&
+                                  that.getValidValues()   == null &&
+                                  that.getMinimumValue()  == null &&
+                                  that.getMaximumValue()  == null;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Null-safe string representation of the given identifier, for comparison 
purpose.
+     * We ignore codespace because they can not be represented in ISO 19139 
XML documents.
+     */
+    private static String toString(final Identifier identifier) {
+        return (identifier != null) ? identifier.toString() : null;
+    }
+}
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/QualityParameter.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/QualityParameter.java
new file mode 100644
index 0000000000..fc7dcb875b
--- /dev/null
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/QualityParameter.java
@@ -0,0 +1,245 @@
+/*
+ * 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.metadata.replace;
+
+import java.util.Map;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import org.opengis.util.TypeName;
+import org.opengis.util.InternationalString;
+import org.opengis.metadata.Identifier;
+import org.opengis.metadata.quality.Description;
+import org.opengis.metadata.quality.ValueStructure;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.referencing.operation.Matrix;
+import org.apache.sis.metadata.iso.DefaultIdentifier;
+import org.apache.sis.metadata.iso.quality.DefaultDescription;
+import org.apache.sis.internal.jaxb.gco.GO_GenericName;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.iso.Names;
+import org.apache.sis.xml.Namespaces;
+
+// Branch-dependent imports
+import org.opengis.coverage.Coverage;
+
+
+/**
+ * Parameter information conform to the ISO 19157:2013 specification.
+ * GeoAPI tries to provides a single API for the parameter classes defined in 
various specifications
+ * (ISO 19111, ISO 19115, ISO 19157, Web Processing Service).
+ * But we still need separated representations at XML (un)marshalling time.
+ * This class is for the ISO 19157:2013 case.
+ *
+ * <p>Note that this implementation is simple and serves no other purpose than 
being a container for XML
+ * parsing and formatting. For real parameter framework, consider using {@link 
org.apache.sis.parameter}
+ * package instead.</p>
+ *
+ * <h2>Note about raw-type usage</h2>
+ * We use raw type (i.e. we implement {@code ParameterDescriptor} instead of 
{@code ParameterDescriptor<T>})
+ * because there is no way we can know {@code <T>} for sure at unmarshalling 
time. This is not a recommended
+ * practice, so <strong>this class shall not be in public API</strong>.  
However it should be okay to create
+ * {@code QualityParameter} instances in Apache SIS internal code if all 
methods creating such instances
+ * declare {@code ParameterDescriptor<?>} as their return type.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since   1.3
+ * @module
+ */
+@SuppressWarnings("rawtypes")   // For the omission of <T> in Parameter<T> - 
see javadoc.
+@XmlType(name = "DQM_Parameter_Type", namespace = Namespaces.DQM, propOrder = {
+    "code",
+    "definition",
+    "description",
+    "valueType",
+    "valueStructure"
+})
+@XmlRootElement(name = "DQM_Parameter", namespace = Namespaces.DQM)
+public final class QualityParameter extends Parameter {
+    /**
+     * Name of the data quality parameter, to be represented as identifier 
code.
+     *
+     * @see #getName()
+     */
+    @XmlElement(name="name", required=true)
+    String code;
+
+    /**
+     * Definition of the data quality parameter.
+     * Stored in {@link Identifier#getDescription()}.
+     *
+     * @see #getName()
+     */
+    @XmlElement(required = true)
+    InternationalString definition;
+
+    /**
+     * Description of the data quality parameter.
+     *
+     * @see #getDescription()
+     */
+    @XmlElement
+    Description description;
+
+    /**
+     * Value type of the data quality parameter (shall be one of the data 
types defined in ISO/TS 19103:2005).
+     *
+     * @see #getValueType()
+     * @see #getValueClass()
+     */
+    @XmlElement(required = true)
+    @XmlJavaTypeAdapter(GO_GenericName.class)   // Not in package-info because 
shall not be applied to getLegacyName().
+    TypeName valueType;
+
+    /**
+     * Structure of the data quality parameter.
+     *
+     * @see #getValueClass()
+     */
+    @XmlElement
+    ValueStructure valueStructure;
+
+    /**
+     * Creates an initially empty parameter.
+     * This constructor is needed by JAXB at unmarshalling time.
+     *
+     * <p><strong>Consider this constructor as private</strong> except for 
testing purpose.
+     * See <cite>Note about raw-type usage</cite> in class javadoc.</p>
+     */
+    QualityParameter() {
+    }
+
+    /**
+     * Creates a parameter initialized to the values of the given one.
+     * This is used for marshalling an arbitrary parameter as an ISO 19157 
parameter.
+     */
+    @SuppressWarnings("unchecked")
+    private QualityParameter(final ParameterDescriptor<?> parameter) {
+        super(parameter);
+        final Identifier id = parameter.getName();
+        if (id != null) {
+            code = id.getCode();
+            definition = id.getDescription();
+        }
+        InternationalString text = parameter.getDescription();
+        if (text != null) {
+            description = new DefaultDescription(text);
+        }
+        valueType = parameter.getValueType();
+        valueStructure = 
ValueStructure.valueOf(parameter.getValueClass()).orElse(null);
+    }
+
+    /**
+     * Returns the given parameter as an instance of {@code QualityParameter}.
+     *
+     * @param  parameter  the parameter (may be {@code null}).
+     * @return the service parameter, or {@code null} if the given argument 
was null.
+     */
+    public static QualityParameter castOrCopy(final ParameterDescriptor<?> 
parameter) {
+        if (parameter == null || parameter instanceof QualityParameter) {
+            return (QualityParameter) parameter;
+        }
+        return new QualityParameter(parameter);
+    }
+
+    /**
+     * Returns the name as an {@code Identifier}, which is the type requested 
by ISO 19111.
+     * Note that this is different than the type requested by ISO 19157, which 
is {@link String}.
+     *
+     * @return the parameter name as an identifier (the type specified by ISO 
19111).
+     */
+    @Override
+    public synchronized Identifier getName() {
+        if (name == null && code != null) {
+            final DefaultIdentifier id = new DefaultIdentifier(code);
+            id.setDescription(definition);
+            id.transitionTo(DefaultIdentifier.State.FINAL);
+            name = id;
+        }
+        return name;
+    }
+
+    /**
+     * Returns a narrative explanation of the role of the parameter.
+     *
+     * @return a narrative explanation of the role of the parameter, or {@code 
null} if none.
+     */
+    @Override
+    public InternationalString getDescription() {
+        final Description description = this.description;
+        return (description != null) ? description.getTextDescription() : null;
+    }
+
+    /**
+     * Infers the value class from the type name.
+     * This method is the reason why we can not parameterize this {@code 
QualityParameter} class
+     * (see <cite>Note about raw-type usage</cite> in class javadoc), because 
there is no way we
+     * can ensure that the class inferred from {@link #valueType} is really 
for type {@code <T>}.
+     *
+     * @return the value class inferred from the attribute type, or {@code 
null} if unknown.
+     */
+    @Override
+    public Class<?> getValueClass() {
+        Class<?> type = super.getValueClass();
+        if (type == null) {
+            final ValueStructure s = valueStructure;
+            type = (s != null) ? s.toJavaType().orElse(null) : 
Names.toClass(valueType);
+        }
+        return type;
+    }
+
+    /**
+     * Returns the name that describes the type of parameter values.
+     *
+     * @return the type name of value component(s) in this parameter.
+     */
+    @Override
+    public TypeName getValueType() {
+        return valueType;
+    }
+
+    /**
+     * Suggests a type name for the components of given collection or array 
class.
+     * The component type is fetched on a <cite>best effort</cite> basis only.
+     * This method does the following checks:
+     * <ul>
+     *   <li>If the given class is a class, then its {@linkplain 
Class#getComponentType() component type} is used.</li>
+     *   <li>Otherwise if the class is an {@link Iterable}, then the upper 
bound of elements is fetched.</li>
+     *   <li>Otherwise if the class is a {@link Map}, then the upper bound of 
keys is fetched.</li>
+     *   <li>Otherwise if the class is a {@link Matrix} or {@link Coverage}, 
then {@link Double} components is assumed.</li>
+     *   <li>Otherwise the given class is used as if it was already a 
component type (i.e. a singleton item).</li>
+     * </ul>
+     *
+     * This method is used for mapping {@link Class} to ({@link 
ValueStructure}, {@link TypeName}) pair.
+     * The other member of the pair is given by {@link 
ValueStructure#valueOf(Class)}.
+     *
+     * @param  valueClass  the type of values for which to infer a {@link 
TypeName} instance.
+     * @return a type name for components of the given type.
+     */
+    public static TypeName getValueType(Class<?> valueClass) {
+        if (valueClass.isArray()) {
+            valueClass = valueClass.getComponentType();
+        } else if (Iterable.class.isAssignableFrom(valueClass) || 
Map.class.isAssignableFrom(valueClass)) {
+            valueClass = Classes.boundOfParameterizedDeclaration(valueClass);
+        } else if (Matrix.class.isAssignableFrom(valueClass) || 
Coverage.class.isAssignableFrom(valueClass)) {
+            valueClass = Double.class;
+        }
+        return Names.createTypeName(valueClass);
+    }
+}
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java
index 7613231284..350daf8bb5 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameter.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.internal.jaxb.metadata.replace;
 
-import java.util.Objects;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -26,30 +25,25 @@ import org.opengis.util.MemberName;
 import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.Identifier;
-import org.opengis.parameter.ParameterValue;
 import org.opengis.parameter.ParameterDirection;
 import org.opengis.parameter.ParameterDescriptor;
-import org.apache.sis.internal.simple.SimpleIdentifiedObject;
 import org.apache.sis.internal.jaxb.FilterByVersion;
 import org.apache.sis.internal.xml.LegacyNamespaces;
 import org.apache.sis.internal.jaxb.gco.GO_GenericName;
-import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.metadata.NameToIdentifier;
 import org.apache.sis.util.iso.DefaultMemberName;
 import org.apache.sis.util.iso.Names;
 import org.apache.sis.xml.Namespaces;
-import org.apache.sis.util.ComparisonMode;
-import org.apache.sis.util.resources.Errors;
 
-import static org.apache.sis.util.Utilities.deepEquals;
 import static org.apache.sis.internal.util.CollectionsExt.nonNull;
 
 
 /**
  * Parameter information conform to the ISO 19115:2014 specification.
  * GeoAPI tries to provides a single API for the parameter classes defined in 
various specifications
- * (ISO 19111, ISO 19115, Web Processing Service). But we still need separated 
representations at XML
- * (un)marshalling time. This class is for the ISO 19115:2014 case.
+ * (ISO 19111, ISO 19115, ISO 19157, Web Processing Service).
+ * But we still need separated representations at XML (un)marshalling time.
+ * This class is for the ISO 19115:2014 case.
  *
  * <p>Note that this implementation is simple and serves no other purpose than 
being a container for XML
  * parsing and formatting. For real parameter framework, consider using {@link 
org.apache.sis.parameter}
@@ -59,16 +53,16 @@ import static 
org.apache.sis.internal.util.CollectionsExt.nonNull;
  * We use raw type (i.e. we implement {@code ParameterDescriptor} instead of 
{@code ParameterDescriptor<T>})
  * because there is no way we can know {@code <T>} for sure at unmarshalling 
time. This is not a recommended
  * practice, so <strong>this class shall not be in public API</strong>.  
However it should be okay to create
- * {@code ServiceMetadata} instances in Apache SIS internal code if all 
methods creating such instances declare
- * {@code ParameterDescriptor<?>} as their return type.
+ * {@code ServiceParameter} instances in Apache SIS internal code if all 
methods creating such instances
+ * declare {@code ParameterDescriptor<?>} as their return type.
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.3
  * @since   0.5
  * @module
  */
-@SuppressWarnings("rawtypes")               // For the omission of <T> in 
ParameterDescriptor<T> - see javadoc.
+@SuppressWarnings("rawtypes")   // For the omission of <T> in Parameter<T> - 
see javadoc.
 @XmlType(name = "SV_Parameter_Type", namespace = Namespaces.SRV, propOrder = {
     "memberName",           // The  ISO 19115-3:2016 way to marshal name.
     "legacyName",           // Legacy ISO 19139:2007 way to marshal name.
@@ -77,15 +71,10 @@ import static 
org.apache.sis.internal.util.CollectionsExt.nonNull;
     "optionality",
     "optionalityLabel",     // Legacy ISO 19139:2007 way to marshal 
optionality.
     "repeatability",
-    "valueType"
+    "legacyValueType"
 })
 @XmlRootElement(name = "SV_Parameter", namespace = Namespaces.SRV)
-public final class ServiceParameter extends SimpleIdentifiedObject implements 
ParameterDescriptor {
-    /**
-     * Serial number for compatibility with different versions.
-     */
-    private static final long serialVersionUID = -5335736212313243889L;
-
+public final class ServiceParameter extends Parameter {
     /**
      * The name, as used by the service for this parameter. Note that in ISO 
19115-3:2016, this element is
      * inside a {@code <gco:MemberName>} element  (i.e. ISO inserts the same 
kind of {@code Property_Type}
@@ -102,6 +91,7 @@ public final class ServiceParameter extends 
SimpleIdentifiedObject implements Pa
      *   </srv:name>
      * }
      *
+     * @see #getName()
      * @see #getLegacyName()
      * @see #getValueType()
      */
@@ -111,12 +101,16 @@ public final class ServiceParameter extends 
SimpleIdentifiedObject implements Pa
 
     /**
      * Indication if the parameter is an input to the service, an output or 
both.
+     *
+     * @see #getDirection()
      */
     @XmlElement(required = true)
     ParameterDirection direction;
 
     /**
      * A narrative explanation of the role of the parameter.
+     *
+     * @see #getDescription()
      */
     @XmlElement
     InternationalString description;
@@ -131,24 +125,21 @@ public final class ServiceParameter extends 
SimpleIdentifiedObject implements Pa
      *
      * @see #getOptionality()
      * @see #setOptionality(Boolean)
+     * @see #getMinimumOccurs()
      */
-    public boolean optionality;
+    boolean optionality;
 
     /**
      * Indication if more than one value of the parameter may be provided.
+     *
+     * @see #getMaximumOccurs()
      */
     @XmlElement(required = true)
-    public boolean repeatability;
-
-    /**
-     * A copy of {@code this} as a fully-implemented parameter descriptor.
-     * This is created when first needed for implementation of {@link 
#createValue()}.
-     */
-    private transient ParameterDescriptor descriptor;
+    boolean repeatability;
 
     /**
      * Creates an initially empty parameter.
-     * This constructor is needed by JAXB.
+     * This constructor is needed by JAXB at unmarshalling time.
      *
      * <p><strong>Consider this constructor as private</strong> except for 
testing purpose.
      * See <cite>Note about raw-type usage</cite> in class javadoc.</p>
@@ -158,7 +149,11 @@ public final class ServiceParameter extends 
SimpleIdentifiedObject implements Pa
 
     /**
      * Creates a parameter initialized to the values of the given one.
+     * This is used for marshalling an arbitrary parameter as an ISO 19115 
parameter.
+     *
+     * @see #castOrCopy(ParameterDescriptor)
      */
+    @SuppressWarnings("unchecked")
     private ServiceParameter(final ParameterDescriptor<?> parameter) {
         super(parameter);
         memberName    = getMemberName(parameter);
@@ -182,9 +177,22 @@ public final class ServiceParameter extends 
SimpleIdentifiedObject implements Pa
     }
 
     /**
-     * Gets the parameter name as a {@code MemberName}. This method first 
checks if the primary name is an instance of
-     * {@code MemberName}. If not, this method searches for the first alias 
which is an instance of {@code MemberName}.
-     * If none is found, then this method tries to build a member name from 
the primary name and value class.
+     * Gets the parameter name as an instance of {@code MemberName}.
+     * This method performs the following checks:
+     *
+     * <ul>
+     *   <li>If the {@linkplain DefaultParameterDescriptor#getName() primary 
name} is an instance of {@code MemberName},
+     *       returns that primary name.</li>
+     *   <li>Otherwise this method searches for the first {@linkplain 
DefaultParameterDescriptor#getAlias() alias}
+     *       which is an instance of {@code MemberName}. If found, that alias 
is returned.</li>
+     *   <li>If no alias is found, then this method tries to build a member 
name from the primary name and the
+     *       {@linkplain ParameterDescriptor#getValueType() value type} (if 
available) or the
+     *       {@linkplain ParameterDescriptor#getValueClass() value class}.</li>
+     * </ul>
+     *
+     * This method can be used as a bridge between the parameter object
+     * defined by ISO 19111 (namely {@code CC_OperationParameter}) and the one
+     * defined by ISO 19115 (namely {@code SV_Parameter}).
      *
      * @param  parameter  the parameter from which to get the name (may be 
{@code null}).
      * @return the member name, or {@code null} if none.
@@ -201,11 +209,17 @@ public final class ServiceParameter extends 
SimpleIdentifiedObject implements Pa
                 }
             }
             if (id != null) {
-                final Class<?> valueClass = parameter.getValueClass();
-                if (valueClass != null) {
-                    final String code = id.getCode();
-                    if (code != null) {
-                        return Names.createMemberName(id.getCodeSpace(), null, 
code, valueClass);
+                final String code = id.getCode();
+                if (code != null) {
+                    final String namespace = id.getCodeSpace();
+                    final TypeName type = parameter.getValueType();
+                    if (type != null) {
+                        return Names.createMemberName(namespace, null, code, 
type);
+                    } else {
+                        final Class<?> valueClass = parameter.getValueClass();
+                        if (valueClass != null) {
+                            return Names.createMemberName(namespace, null, 
code, valueClass);
+                        }
                     }
                 }
             }
@@ -213,6 +227,26 @@ public final class ServiceParameter extends 
SimpleIdentifiedObject implements Pa
         return null;
     }
 
+    /**
+     * Returns the name as an {@code Identifier}, which is the type requested 
by ISO 19111.
+     * Note that this is different than the type requested by ISO 19115, which 
is {@link MemberName}.
+     *
+     * This method is the converse of {@link 
#getMemberName(ParameterDescriptor)}.
+     *
+     * @return the parameter name as an identifier (the type specified by ISO 
19111).
+     */
+    @Override
+    public synchronized Identifier getName() {
+        if (name == null && memberName != null) {
+            if (memberName instanceof Identifier) {
+                name = (Identifier) memberName;
+            } else {
+                name = new NameToIdentifier(memberName);
+            }
+        }
+        return name;
+    }
+
     /**
      * Returns the name to be marshalled in the ISO 19139:2007 way. Example:
      *
@@ -240,67 +274,49 @@ public final class ServiceParameter extends 
SimpleIdentifiedObject implements Pa
      */
     @SuppressWarnings("unused")
     private void setLegacyName(final DefaultMemberName value) {
-        ensureUndefined();
-        memberName = value;
+        if (memberName == null) {
+            memberName = value;
+        }
     }
 
     /**
-     * Ensures that the {@linkplain #memberName} is not already defined.
-     *
-     * @throws IllegalStateException if a name is already defined.
+     * For JAXB marshalling of ISO 19139:2007 document only.
+     * Note that there is not setter method, because we expect that
+     * the same information is provided in the {@link #memberName} attribute 
type.
      */
-    private void ensureUndefined() throws IllegalStateException {
-        if (memberName != null) {
-            throw new 
IllegalStateException(Errors.format(Errors.Keys.ValueAlreadyDefined_1, "name"));
-        }
+    @XmlElement(name = "valueType", namespace = LegacyNamespaces.SRV)
+    @XmlJavaTypeAdapter(GO_GenericName.class)    // Not in package-info 
because shall not be applied to getLegacyName().
+    private TypeName getLegacyValueType() {
+        return FilterByVersion.LEGACY_METADATA.accept() ? getValueType() : 
null;
     }
 
     /**
-     * Returns the name as an {@code Identifier}, which is the type requested 
by ISO 19111.
-     * Note that this is different than the type requested by ISO 19115, which 
is {@link MemberName}.
+     * Returns the name that describes the type of parameter values.
      *
-     * This method is the converse of {@link 
#getMemberName(ParameterDescriptor)}.
-     *
-     * @return the parameter name as an identifier (the type specified by ISO 
19111).
+     * @return the type name of value component(s) in this parameter.
      */
     @Override
-    public synchronized Identifier getName() {
-        if (name == null && memberName != null) {
-            if (memberName instanceof Identifier) {
-                name = (Identifier) memberName;
-            } else {
-                name = new NameToIdentifier(memberName);
-            }
+    public TypeName getValueType() {
+        TypeName type = super.getValueType();
+        if (type == null && memberName != null) {
+            type = memberName.getAttributeType();
         }
-        return name;
+        return type;
     }
 
     /**
      * Infers the value class from the attribute type.
      * This method is the reason why we can not parameterize this {@code 
ServiceParameter} class
-     * (see <cite>Note about raw-type usage</cite> in class javadoc), since 
there is no way we
-     * can ensure that the returned class is really for type {@code <T>}.
+     * (see <cite>Note about raw-type usage</cite> in class javadoc), because 
there is no way we
+     * can ensure that the class inferred from {@link 
MemberName#getAttributeType()} is really
+     * for type {@code <T>}.
      *
      * @return the value class inferred from the attribute type, or {@code 
null} if unknown.
      */
     @Override
     public Class<?> getValueClass() {
-        return (memberName != null) ? 
Names.toClass(memberName.getAttributeType()) : null;
-    }
-
-    /**
-     * For JAXB marshalling of ISO 19139:2007 document only.
-     * Note that there is not setter method, since we expect the same 
information
-     * to be provided in the {@link #name} attribute type.
-     */
-    @Override
-    @XmlElement(name = "valueType", namespace = LegacyNamespaces.SRV)
-    @XmlJavaTypeAdapter(GO_GenericName.class)    // Not in package-info 
because shall not be applied to getLegacyName().
-    public final TypeName getValueType() {
-        if (memberName != null && FilterByVersion.LEGACY_METADATA.accept()) {
-            return memberName.getAttributeType();
-        }
-        return null;
+        final Class<?> type = super.getValueClass();
+        return (type != null) ? type : Names.toClass(getValueType());
     }
 
     /**
@@ -375,65 +391,4 @@ public final class ServiceParameter extends 
SimpleIdentifiedObject implements Pa
     public int getMaximumOccurs() {
         return repeatability ? Integer.MAX_VALUE : 1;
     }
-
-    /**
-     * Creates a new instance of {@code ParameterValue}.
-     * This method delegates the work to {@link 
org.apache.sis.parameter.DefaultParameterDescriptor}
-     * since this {@code ServiceParameter} class is not a full-featured 
parameter descriptor implementation.
-     *
-     * @return a new instance of {@code ParameterValue}.
-     */
-    @Override
-    public ParameterValue<?> createValue() {
-        ParameterDescriptor<?> desc;
-        synchronized (this) {
-            desc = descriptor;
-            if (desc == null) {
-                descriptor = desc = 
ReferencingServices.getInstance().toImplementation(this);
-            }
-        }
-        return desc.createValue();
-    }
-
-    /**
-     * Compares this object with the given one for equality.
-     *
-     * @param  object  the object to compare with this reference system.
-     * @param  mode    the strictness level of the comparison.
-     * @return {@code true} if both objects are equal.
-     */
-    @Override
-    public boolean equals(final Object object, final ComparisonMode mode) {
-        if (object == this) {
-            return true;
-        }
-        if (super.equals(object, mode) && object instanceof 
ParameterDescriptor<?>) {
-            final ParameterDescriptor<?> that = (ParameterDescriptor<?>) 
object;
-            if (that.getUnit()         == null &&
-                that.getDefaultValue() == null &&
-                that.getValueClass()   == getValueClass())
-            {
-                if (mode.isIgnoringMetadata()) {
-                    return Objects.equals(toString(getName()), 
toString(that.getName()));
-                    // super.equals(…) already compared 'getName()' in others 
mode.
-                }
-                return deepEquals(that.getDescription(), getDescription(), 
mode) &&
-                                  that.getDirection()     == getDirection()    
 &&
-                                  that.getMinimumOccurs() == 
getMinimumOccurs() &&
-                                  that.getMaximumOccurs() == 
getMaximumOccurs() &&
-                                  that.getValidValues()   == null &&
-                                  that.getMinimumValue()  == null &&
-                                  that.getMaximumValue()  == null;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Null-safe string representation of the given identifier, for comparison 
purpose.
-     * We ignore codespace because they can not be represented in ISO 19139 
XML documents.
-     */
-    private static String toString(final Identifier identifier) {
-        return (identifier != null) ? identifier.toString() : null;
-    }
 }
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/package-info.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/package-info.java
index 9e564921e0..8d09ded25c 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/package-info.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/replace/package-info.java
@@ -19,18 +19,19 @@
  * Classes that are normally omitted from public API because they duplicate 
existing classes,
  * but still temporarily used at XML (un)marshalling time for standards 
compliance.
  *
- * <p>Some objects defined in various standards have overlapping 
functionalities. For example the
- * Metadata (ISO 19115), Referencing by Coordinates (ISO 19111) and Web 
Processing Service (WPS)
- * all define their own parameter objects. An other example is ISO 19115 
defining basic referencing
- * information, which is clearly ISO 19111 subject. GeoAPI tries to provide a 
uniform API by merging
- * objects, or by omitting an object from one standard in favor of the 
equivalent object of another
- * standard. However at XML (un)marshalling time, we still need to temporarily 
recreate the omitted
- * object as defined in the original standard. This package is used for such 
replacement.</p>
+ * <p>Some objects defined in various standards have overlapping 
functionalities.
+ * For example the Metadata (ISO 19115), Referencing by Coordinates (ISO 
19111),
+ * Data Quality (ISO 19157) and Web Processing Service (WPS) standards all 
define their own parameter objects.
+ * An other example is ISO 19115 defining basic referencing information, which 
is clearly ISO 19111 work.
+ * GeoAPI tries to provide an uniform API by merging objects, or by omitting 
an object from one standard
+ * in favor of the equivalent object of another standard. However at XML 
(un)marshalling time,
+ * we still need to temporarily recreate the omitted object as defined in the 
original standard.
+ * This package is used for such replacement.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Rémi Maréchal (Geomatys)
  * @author  Cullen Rombach (Image Matters)
- * @since   1.0
+ * @since   1.3
  * @since   0.5
  * @module
  */
@@ -45,6 +46,8 @@
 @XmlJavaTypeAdapters({
     @XmlJavaTypeAdapter(GO_Boolean.class),
     @XmlJavaTypeAdapter(MD_Identifier.class),
+    @XmlJavaTypeAdapter(DQM_Description.class),
+    @XmlJavaTypeAdapter(DQM_ValueStructure.class),
     @XmlJavaTypeAdapter(SV_ParameterDirection.class),
 
     // Java types, primitive types and basic OGC types handling
@@ -63,6 +66,8 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
 import org.apache.sis.internal.xml.LegacyNamespaces;
 import org.apache.sis.internal.jaxb.metadata.MD_Identifier;
+import org.apache.sis.internal.jaxb.metadata.DQM_Description;
 import org.apache.sis.internal.jaxb.code.SV_ParameterDirection;
+import org.apache.sis.internal.jaxb.code.DQM_ValueStructure;
 import org.apache.sis.internal.jaxb.gco.*;
 import org.apache.sis.xml.Namespaces;
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
index b3de0b6559..9503ab5e1e 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
@@ -45,7 +45,7 @@ import org.apache.sis.internal.system.Modules;
  * <cite>"referencing by coordinates"</cite> but needed by metadata.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -253,13 +253,14 @@ public class ReferencingServices extends 
OptionalDependency {
     /**
      * Returns a fully implemented parameter descriptor.
      *
+     * @param  <T>        the type of values.
      * @param  parameter  a partially implemented parameter descriptor, or 
{@code null}.
      * @return a fully implemented parameter descriptor, or {@code null} if 
the given argument was null.
      * @throws UnsupportedOperationException if the {@code "sis-referencing"} 
module has not been found on the classpath.
      *
      * @since 0.5
      */
-    public ParameterDescriptor<?> toImplementation(ParameterDescriptor<?> 
parameter) {
+    public <T> ParameterDescriptor<T> toImplementation(ParameterDescriptor<T> 
parameter) {
         throw moduleNotFound();
     }
 
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultMeasure.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultMeasure.java
index 374afc1e82..6ab9a82c89 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultMeasure.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultMeasure.java
@@ -22,11 +22,11 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 import org.opengis.util.TypeName;
 import org.opengis.util.InternationalString;
+import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.quality.Measure;
 import org.opengis.metadata.quality.BasicMeasure;
 import org.opengis.metadata.quality.Description;
-import org.opengis.metadata.quality.Parameter;
 import org.opengis.metadata.quality.SourceReference;
 import org.opengis.metadata.quality.ValueStructure;
 import org.apache.sis.xml.Namespaces;
@@ -145,7 +145,7 @@ public class DefaultMeasure extends ISOMetadata implements 
Measure {
      * Auxiliary variable used by the data quality measure, including its 
name, definition and optionally its description.
      */
     @SuppressWarnings("serial")
-    private Collection<Parameter> parameters;
+    private Collection<ParameterDescriptor<?>> parameters;
 
     /**
      * Illustration of the use of a data quality measure.
@@ -168,7 +168,7 @@ public class DefaultMeasure extends ISOMetadata implements 
Measure {
      *
      * @see #castOrCopy(Measure)
      */
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public DefaultMeasure(final Measure object) {
         super(object);
         if (object != null) {
@@ -183,7 +183,7 @@ public class DefaultMeasure extends ISOMetadata implements 
Measure {
             examples          = copyCollection(object.getExamples(), 
Description.class);
             basicMeasure      = object.getBasicMeasure();
             sourceReferences  = copyCollection(object.getSourceReferences(), 
SourceReference.class);
-            parameters        = copyCollection(object.getParameters(), 
Parameter.class);
+            parameters        = copyCollection(object.getParameters(), (Class) 
ParameterDescriptor.class);
         }
     }
 
@@ -432,8 +432,9 @@ public class DefaultMeasure extends ISOMetadata implements 
Measure {
      */
     @Override
     @XmlElement(name = "parameter")
-    public Collection<Parameter> getParameters() {
-        return parameters = nonNullCollection(parameters, Parameter.class);
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public Collection<ParameterDescriptor<?>> getParameters() {
+        return parameters = nonNullCollection(parameters, (Class) 
ParameterDescriptor.class);
     }
 
     /**
@@ -441,8 +442,9 @@ public class DefaultMeasure extends ISOMetadata implements 
Measure {
      *
      * @param  newValues  the new measure parameters.
      */
-    public void setParameters(final Collection<? extends Parameter> newValues) 
{
-        parameters = writeCollection(newValues, parameters, Parameter.class);
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public void setParameters(final Collection<? extends 
ParameterDescriptor<?>> newValues) {
+        parameters = writeCollection(newValues, parameters, (Class) 
ParameterDescriptor.class);
     }
 
     /**
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultParameter.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultParameter.java
deleted file mode 100644
index 0c6f649cba..0000000000
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultParameter.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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.metadata.iso.quality;
-
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import org.opengis.util.TypeName;
-import org.opengis.util.InternationalString;
-import org.opengis.metadata.quality.Parameter;
-import org.opengis.metadata.quality.Description;
-import org.opengis.metadata.quality.ValueStructure;
-import org.apache.sis.xml.Namespaces;
-
-
-/**
- * Data quality parameter.
- * The following property is mandatory in a well-formed metadata according ISO 
19157:
- *
- * <div class="preformat">{@code DQM_Parameter}
- * {@code   ├─name……………………} Name of the data quality parameter.
- * {@code   ├─definition……} Definition of the data quality parameter.
- * {@code   └─valueType………} Value type of the data quality parameter (shall be 
one of the data types defined in ISO/TS 19103:2005).</div>
- *
- * <h2>Limitations</h2>
- * <ul>
- *   <li>Instances of this class are not synchronized for multi-threading.
- *       Synchronization, if needed, is caller's responsibility.</li>
- *   <li>Serialized objects of this class are not guaranteed to be compatible 
with future Apache SIS releases.
- *       Serialization support is appropriate for short term storage or RMI 
between applications running the
- *       same version of Apache SIS. For long term storage, use {@link 
org.apache.sis.xml.XML} instead.</li>
- * </ul>
- *
- * @author  Alexis Gaillard (Geomatys)
- * @author  Martin Desruisseaux (Geomatys)
- * @version 1.3
- * @since   1.3
- * @module
- */
-@XmlType(name = "DQM_Parameter_Type", namespace = Namespaces.DQM, propOrder = {
-    "name",
-    "definition",
-    "description",
-    "valueType",
-    "valueStructure"
-})
-@XmlRootElement(name = "DQM_Parameter", namespace = Namespaces.DQM)
-public class DefaultParameter extends ISOMetadata implements Parameter {
-    /**
-     * Serial number for inter-operability with different versions.
-     */
-    private static final long serialVersionUID = -5063371334668144677L;
-
-    /**
-     * Name of the data quality parameter.
-     */
-    @SuppressWarnings("serial")
-    private InternationalString name;
-
-    /**
-     * Definition of the data quality parameter.
-     */
-    @SuppressWarnings("serial")
-    private InternationalString definition;
-
-     /**
-     * Description of the data quality parameter.
-     */
-    @SuppressWarnings("serial")
-    private Description description;
-
-     /**
-     * Value type of the data quality parameter (shall be one of the data 
types defined in ISO/TS 19103:2005).
-     */
-    @SuppressWarnings("serial")
-    private TypeName valueType;
-
-    /**
-     * Structure of the data quality parameter.
-     */
-    private ValueStructure valueStructure;
-
-    /**
-     * Constructs an initially empty element.
-     */
-    public DefaultParameter() {
-    }
-
-    /**
-     * Constructs a new instance initialized with the values from the 
specified metadata object.
-     * This is a <cite>shallow</cite> copy constructor, since the other 
metadata contained in the
-     * given object are not recursively copied.
-     *
-     * @param object  the metadata to copy values from, or {@code null} if 
none.
-     *
-     * @see #castOrCopy(Parameter)
-     */
-    public DefaultParameter(final Parameter object) {
-        super(object);
-        if (object != null) {
-            name           = object.getName();
-            definition     = object.getDefinition();
-            description    = object.getDescription();
-            valueType      = object.getValueType();
-            valueStructure = object.getValueStructure();
-        }
-    }
-
-    /**
-     * Returns a SIS metadata implementation with the values of the given 
arbitrary implementation.
-     * This method performs the first applicable action in the following 
choices:
-     *
-     * <ul>
-     *   <li>If the given object is {@code null}, then this method returns 
{@code null}.</li>
-     *   <li>Otherwise if the given object is already an instance of
-     *       {@code DefaultParameter}, then it is returned unchanged.</li>
-     *   <li>Otherwise a new {@code DefaultParameter} instance is created 
using the
-     *       {@linkplain #DefaultParameter(Parameter) copy constructor} and 
returned.
-     *       Note that this is a <cite>shallow</cite> copy operation, since 
the other
-     *       metadata contained in the given object are not recursively 
copied.</li>
-     * </ul>
-     *
-     * @param  object  the object to get as a SIS implementation, or {@code 
null} if none.
-     * @return a SIS implementation containing the values of the given object 
(may be the
-     *         given object itself), or {@code null} if the argument was null.
-     */
-    public static DefaultParameter castOrCopy(final Parameter object) {
-        if (object == null || object instanceof DefaultParameter) {
-            return (DefaultParameter) object;
-        }
-        return new DefaultParameter(object);
-    }
-
-    /**
-     * Returns the name of the data quality parameter.
-     *
-     * @return name of the data quality parameter.
-     */
-    @Override
-    @XmlElement(name = "name", required = true)
-    public InternationalString getName() {
-        return name;
-    }
-
-    /**
-     * Sets the name of the data quality parameter.
-     *
-     * @param  newValue  the new parameter name.
-     */
-    public void setName(final InternationalString newValue)  {
-        checkWritePermission(name);
-        name = newValue;
-    }
-
-    /**
-     * Returns the definition of the data quality parameter.
-     *
-     * @return definition of the data quality parameter.
-     */
-    @Override
-    @XmlElement(name = "definition", required = true)
-    public InternationalString getDefinition() {
-        return definition;
-    }
-
-    /**
-     * Sets the definition of the data quality parameter.
-     *
-     * @param  newValue  the new parameter definition.
-     */
-    public void setDefinition(final InternationalString newValue)  {
-        checkWritePermission(definition);
-        definition = newValue;
-    }
-
-    /**
-     * Returns the description of the data quality parameter.
-     *
-     * @return description of the data quality parameter, or {@code null} if 
none.
-     */
-    @Override
-    @XmlElement(name = "description")
-    public Description getDescription() {
-       return description;
-    }
-
-    /**
-     * Sets the description of the data quality parameter.
-     *
-     * @param  newValue  the new parameter description.
-     */
-    public void setDescription(final Description newValue)  {
-        checkWritePermission(description);
-        description = newValue;
-    }
-
-    /**
-     * Returns the value type of the data quality parameter.
-     *
-     * @return value type of the data quality parameter.
-     */
-    @Override
-    @XmlElement(name = "valueType", required = true)
-    public TypeName getValueType() {
-        return valueType;
-    }
-
-    /**
-     * Sets the value type of the data quality parameter.
-     *
-     * @param  newValue  the new parameter value type.
-     */
-    public void setValueType(final TypeName newValue)  {
-        checkWritePermission(valueType);
-        valueType = newValue;
-    }
-
-    /**
-     * Returns the structure of the data quality parameter.
-     *
-     * @return structure of the data quality parameter, or {@code null} if 
none.
-     */
-    @Override
-    @XmlElement(name = "valueStructure")
-    public ValueStructure getValueStructure() {
-        return valueStructure;
-    }
-
-    /**
-     * Sets the structure of the data quality parameter.
-     *
-     * @param  newValue  the new parameter value structure.
-     */
-    public void setValueStructure(final ValueStructure newValue)  {
-        checkWritePermission(valueStructure);
-        valueStructure = newValue;
-    }
-}
diff --git 
a/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/metadata/replace/QualityParameterTest.java
 
b/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/metadata/replace/QualityParameterTest.java
new file mode 100644
index 0000000000..b51c43b2f7
--- /dev/null
+++ 
b/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/metadata/replace/QualityParameterTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.metadata.replace;
+
+import javax.xml.bind.JAXBException;
+import org.opengis.metadata.Identifier;
+import org.opengis.referencing.operation.Matrix;
+import org.opengis.metadata.quality.ValueStructure;
+import org.apache.sis.util.iso.Names;
+import org.apache.sis.util.SimpleInternationalString;
+import org.apache.sis.metadata.iso.quality.DefaultDescription;
+import org.apache.sis.test.xml.TestCase;
+import org.apache.sis.xml.Namespaces;
+import org.junit.Test;
+
+import static org.apache.sis.test.MetadataAssert.*;
+
+
+/**
+ * Tests {@link QualityParameter}.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since   1.3
+ * @module
+ */
+public final strictfp class QualityParameterTest extends TestCase {
+    /**
+     * Creates the parameter to use for testing purpose.
+     *
+     * @return the test parameter.
+     */
+    public static QualityParameter create() {
+        final QualityParameter param = new QualityParameter();
+        param.code           = "some parameter";
+        param.definition     = new SimpleInternationalString("a definition");
+        param.description    = new DefaultDescription("a description");
+        param.valueStructure = ValueStructure.MATRIX;
+        param.valueType      = Names.createTypeName(Integer.class);
+        return param;
+    }
+
+    /**
+     * Tests {@link QualityParameter#getName()}.
+     */
+    @Test
+    public void testGetName() {
+        final QualityParameter param = create();
+        final Identifier name = param.getName();
+        assertNull  ("codeSpace", name.getCodeSpace());
+        assertEquals("code", "some parameter", name.getCode());
+        assertEquals("definition",  "a definition",  String.valueOf(name 
.getDescription()));
+        assertEquals("description", "a description", 
String.valueOf(param.getDescription()));
+    }
+
+    /**
+     * Tests {@link QualityParameter#getValueType()} and {@link 
QualityParameter#getValueClass()}.
+     */
+    @Test
+    public void testGetValueType() {
+        final QualityParameter param = create();
+        assertEquals("valueClass", Matrix.class, param.getValueClass());
+        assertEquals("valueType", "OGC:Integer", 
param.getValueType().toFullyQualifiedName().toString());
+    }
+
+    /**
+     * Tests marshalling of a parameter.
+     *
+     * @throws JAXBException if an error occurred during marshalling.
+     */
+    @Test
+    public void testMarshal() throws JAXBException {
+        final String xml = marshal(create());
+        assertXmlEquals(
+                "<dqm:DQM_Parameter xmlns:dqm=\"" + Namespaces.DQM + '"' +
+                                 " xmlns:gco=\"" + Namespaces.GCO + "\">\n" +
+                "  <dqm:name>\n" +
+                "    <gco:CharacterString>some 
parameter</gco:CharacterString>\n" +
+                "  </dqm:name>\n" +
+                "  <dqm:definition>\n" +
+                "    <gco:CharacterString>a 
definition</gco:CharacterString>\n" +
+                "  </dqm:definition>\n" +
+                "  <dqm:description>\n" +
+                "    <dqm:DQM_Description>\n" +
+                "      <dqm:textDescription>\n" +
+                "        <gco:CharacterString>a 
description</gco:CharacterString>\n" +
+                "      </dqm:textDescription>\n" +
+                "    </dqm:DQM_Description>\n" +
+                "  </dqm:description>\n" +
+                "  <dqm:valueType>\n" +
+                "    <gco:TypeName>\n" +
+                "      <gco:aName>\n" +
+                "        <gco:CharacterString>Integer</gco:CharacterString>\n" 
+
+                "      </gco:aName>\n" +
+                "    </gco:TypeName>\n" +
+                "  </dqm:valueType>\n" +
+                "  <dqm:valueStructure>\n" +
+                "    <dqm:DQM_ValueStructure 
codeList=\"http://standards.iso.org/iso/19115/resources/Codelist/cat/codelists.xml#DQM_ValueStructure\"";
+                                         + " 
codeListValue=\"matrix\">Matrix</dqm:DQM_ValueStructure>\n" +
+                "  </dqm:valueStructure>\n" +
+                "</dqm:DQM_Parameter>\n", xml, "xmlns:*");
+    }
+}
diff --git 
a/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameterTest.java
 
b/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameterTest.java
index 0159972364..43f95e4e8f 100644
--- 
a/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameterTest.java
+++ 
b/core/sis-metadata/src/test/java/org/apache/sis/internal/jaxb/metadata/replace/ServiceParameterTest.java
@@ -18,6 +18,7 @@ package org.apache.sis.internal.jaxb.metadata.replace;
 
 import javax.xml.bind.JAXBException;
 import org.opengis.util.MemberName;
+import org.opengis.metadata.Identifier;
 import org.opengis.parameter.ParameterDirection;
 import org.apache.sis.xml.Namespaces;
 import org.apache.sis.util.iso.Names;
@@ -32,7 +33,7 @@ import static org.apache.sis.test.MetadataAssert.*;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Cullen Rombach (Image Matters)
- * @version 1.0
+ * @version 1.3
  * @since   0.5
  * @module
  */
@@ -43,9 +44,9 @@ public final strictfp class ServiceParameterTest extends 
TestCase {
      * @return the test parameter.
      */
     public static ServiceParameter create() {
-        final MemberName paramName = Names.createMemberName(null, null, 
"Version", String.class);
+        final MemberName name = Names.createMemberName("TestSpace", null, "My 
service parameter", String.class);
         final ServiceParameter param = new ServiceParameter();
-        param.memberName    = paramName;
+        param.memberName    = name;
         param.optionality   = true;
         param.repeatability = false;
         param.direction     = ParameterDirection.IN;
@@ -58,8 +59,11 @@ public final strictfp class ServiceParameterTest extends 
TestCase {
     @Test
     public void testGetName() {
         final ServiceParameter param = create();
-        assertEquals("name", "Version", String.valueOf(param.getName()));
-        assertEquals("valueClass", String.class, param.getValueClass());
+        final Identifier name = param.getName();
+        assertEquals("codeSpace", "TestSpace", name.getCodeSpace());
+        assertEquals("code", "My service parameter", name.getCode());
+        assertEquals("name", "TestSpace:My service parameter", 
String.valueOf(name));
+        assertNull  ("description", param.getDescription());
     }
 
     /**
diff --git 
a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/AllMetadataTest.java
 
b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/AllMetadataTest.java
index 6d0022a27c..d6f133dc60 100644
--- 
a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/AllMetadataTest.java
+++ 
b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/AllMetadataTest.java
@@ -191,7 +191,6 @@ public final strictfp class AllMetadataTest extends 
PropertyConsistencyCheck {
             org.opengis.metadata.quality.Metaquality.class,
             
org.opengis.metadata.quality.NonQuantitativeAttributeAccuracy.class,
             
org.opengis.metadata.quality.NonQuantitativeAttributeCorrectness.class,
-            org.opengis.metadata.quality.Parameter.class,
             org.opengis.metadata.quality.PositionalAccuracy.class,
             org.opengis.metadata.quality.QuantitativeAttributeAccuracy.class,
             org.opengis.metadata.quality.QuantitativeResult.class,
diff --git 
a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultServiceIdentificationTest.java
 
b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultServiceIdentificationTest.java
index 9ee068456b..63e0e8a3fc 100644
--- 
a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultServiceIdentificationTest.java
+++ 
b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/identification/DefaultServiceIdentificationTest.java
@@ -97,10 +97,10 @@ public final strictfp class 
DefaultServiceIdentificationTest extends TestUsingFi
         assertEquals("connectPoints", NilReason.MISSING, 
NilReason.forObject(getSingleton(op.getConnectPoints())));
 
         final ParameterDescriptor<?> param = getSingleton(op.getParameters());
-        assertEquals("name",          "Version",             
String.valueOf(param.getName()));
-        assertEquals("minimumOccurs", 0,                     
param.getMinimumOccurs());
-        assertEquals("maximumOccurs", 1,                     
param.getMaximumOccurs());
-        assertEquals("direction",     ParameterDirection.IN, 
param.getDirection());
+        assertEquals("name", "My service parameter", 
String.valueOf(param.getName()));
+        assertEquals("minimumOccurs", 0, param.getMinimumOccurs());
+        assertEquals("maximumOccurs", 1, param.getMaximumOccurs());
+        assertEquals("direction", ParameterDirection.IN, param.getDirection());
     }
 
     /**
diff --git 
a/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
 
b/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
index f570c1bf7d..7a16422d54 100644
--- 
a/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
+++ 
b/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
@@ -116,6 +116,7 @@ import org.junit.BeforeClass;
     org.apache.sis.metadata.iso.identification.DefaultBrowseGraphicTest.class,
     
org.apache.sis.metadata.iso.identification.DefaultDataIdentificationTest.class,
     org.apache.sis.internal.jaxb.metadata.replace.ServiceParameterTest.class,
+    org.apache.sis.internal.jaxb.metadata.replace.QualityParameterTest.class,
     
org.apache.sis.metadata.iso.identification.DefaultCoupledResourceTest.class,
     
org.apache.sis.metadata.iso.identification.DefaultServiceIdentificationTest.class,
     org.apache.sis.metadata.iso.quality.AbstractElementTest.class,
diff --git 
a/core/sis-metadata/src/test/resources/org/apache/sis/metadata/xml/2007/ServiceIdentification.xml
 
b/core/sis-metadata/src/test/resources/org/apache/sis/metadata/xml/2007/ServiceIdentification.xml
index 209225e18d..172a10d807 100644
--- 
a/core/sis-metadata/src/test/resources/org/apache/sis/metadata/xml/2007/ServiceIdentification.xml
+++ 
b/core/sis-metadata/src/test/resources/org/apache/sis/metadata/xml/2007/ServiceIdentification.xml
@@ -66,7 +66,7 @@
         <srv:SV_Parameter>
           <srv:name>
             <gco:aName>
-              <gco:CharacterString>Version</gco:CharacterString>
+              <gco:CharacterString>My service parameter</gco:CharacterString>
             </gco:aName>
             <gco:attributeType>
               <gco:TypeName>
diff --git 
a/core/sis-metadata/src/test/resources/org/apache/sis/metadata/xml/2016/ServiceIdentification.xml
 
b/core/sis-metadata/src/test/resources/org/apache/sis/metadata/xml/2016/ServiceIdentification.xml
index 6ee13679d3..ce54e7bf1d 100644
--- 
a/core/sis-metadata/src/test/resources/org/apache/sis/metadata/xml/2016/ServiceIdentification.xml
+++ 
b/core/sis-metadata/src/test/resources/org/apache/sis/metadata/xml/2016/ServiceIdentification.xml
@@ -70,7 +70,7 @@
               <srv:name>
                 <gco:MemberName>
                   <gco:aName>
-                    <gco:CharacterString>Version</gco:CharacterString>
+                    <gco:CharacterString>My service 
parameter</gco:CharacterString>
                   </gco:aName>
                   <gco:attributeType>
                     <gco:TypeName>
@@ -111,7 +111,7 @@
           <srv:name>
             <gco:MemberName>
               <gco:aName>
-                <gco:CharacterString>Version</gco:CharacterString>
+                <gco:CharacterString>My service parameter</gco:CharacterString>
               </gco:aName>
               <gco:attributeType>
                 <gco:TypeName>
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
index 88bf198f26..0ea509b445 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
@@ -75,7 +75,7 @@ import static java.util.logging.Logger.getLogger;
  * Implements the referencing services needed by the {@code "sis-metadata"} 
module.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.3
  * @since   0.5
  * @module
  */
@@ -461,11 +461,12 @@ public final class ServicesForMetadata extends 
ReferencingServices {
     /**
      * Returns a fully implemented parameter descriptor.
      *
+     * @param  <T>        the type of values.
      * @param  parameter  a partially implemented parameter descriptor, or 
{@code null}.
      * @return a fully implemented parameter descriptor, or {@code null} if 
the given argument was null.
      */
     @Override
-    public ParameterDescriptor<?> toImplementation(final 
ParameterDescriptor<?> parameter) {
+    public <T> ParameterDescriptor<T> toImplementation(final 
ParameterDescriptor<T> parameter) {
         return DefaultParameterDescriptor.castOrCopy(parameter);
     }
 
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
index 16cc89e3a7..c664309e4c 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
@@ -32,13 +32,13 @@ import org.apache.sis.util.Numbers;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.iso.Names;
 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.metadata.replace.QualityParameter;
 import org.apache.sis.internal.jaxb.referencing.CC_OperationParameter;
 import org.apache.sis.referencing.IdentifiedObjects;
 
@@ -319,25 +319,22 @@ public class DefaultParameterDescriptor<T> extends 
AbstractParameterDescriptor i
      * This is closely related to the {@link Class} returned by {@link 
#getValueClass()}:
      *
      * <ul>
-     *   <li>If the value class is a collection ({@link java.util.Map}, {@link 
Set}, {@link java.util.List} or array),
+     *   <li>If the value class is a collection (e.g. {@link java.util.List} 
or array),
      *       then this method returns the type of <em>elements</em> in the 
collection.</li>
      *   <li>Otherwise this method returns the value class using the mapping 
documented in
      *       {@link org.apache.sis.util.iso.DefaultTypeName} javadoc.</li>
      * </ul>
      *
+     * {@code TypeName} is used for encoding parameters in XML or JSON 
documents,
+     * while {@link #getValueClass()} is used for programmatic purposes.
+     *
      * @return the type name of value component(s) in this parameter.
      *
      * @since 1.3
      */
     @Override
-    public final TypeName getValueType() {
-        Class<?> type = valueClass;
-        if (Iterable.class.isAssignableFrom(type) || 
Map.class.isAssignableFrom(type)) {
-            type = Classes.boundOfParameterizedDeclaration(valueClass);
-        } else if (type.isArray()) {
-            type = type.getComponentType();
-        }
-        return Names.createTypeName(type);
+    public TypeName getValueType() {
+        return QualityParameter.getValueType(valueClass);
     }
 
     /**
@@ -511,11 +508,12 @@ public class DefaultParameterDescriptor<T> extends 
AbstractParameterDescriptor i
                     return getMinimumOccurs() == that.getMinimumOccurs() &&
                            getMaximumOccurs() == that.getMaximumOccurs() &&
                            getValueClass()    == that.getValueClass()    &&
-                           Objects.    equals(getValidValues(),  
that.getValidValues())  &&
-                           Objects.    equals(getMinimumValue(), 
that.getMinimumValue()) &&
-                           Objects.    equals(getMaximumValue(), 
that.getMaximumValue()) &&
-                           Objects.deepEquals(getDefaultValue(), 
that.getDefaultValue()) &&
-                           Utilities.deepEquals(getUnit(),       
that.getUnit(), mode);
+                           Utilities.deepEquals(getValueType(),    
that.getValueType(), mode) &&
+                           Objects.      equals(getValidValues(),  
that.getValidValues())  &&
+                           Objects.      equals(getMinimumValue(), 
that.getMinimumValue()) &&
+                           Objects.      equals(getMaximumValue(), 
that.getMaximumValue()) &&
+                           Objects  .deepEquals(getDefaultValue(), 
that.getDefaultValue()) &&
+                           Utilities.deepEquals(getUnit(),         
that.getUnit(), mode);
                 }
                 case STRICT: {
                     final DefaultParameterDescriptor<?> that = 
(DefaultParameterDescriptor<?>) object;

Reply via email to