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;