You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2014/03/05 17:23:54 UTC
svn commit: r1574562 - in /sis/branches/JDK7/core:
sis-metadata/src/main/java/org/apache/sis/metadata/iso/
sis-referencing/src/main/java/org/apache/sis/parameter/
sis-referencing/src/main/java/org/apache/sis/referencing/
sis-referencing/src/test/java/o...
Author: desruisseaux
Date: Wed Mar 5 16:23:53 2014
New Revision: 1574562
URL: http://svn.apache.org/r1574562
Log:
Refactored the builder: moved all identification information (i.e. properties related to IdentifiedObject)
to a new super class, to be shared by the Datum, CS and CRS builder to be provided in a future SIS version.
Renamed the remaining of DescriptorBuilder as ParameterBuilder for clarity.
Added:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
- copied, changed from r1574221, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DescriptorBuilder.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
- copied, changed from r1574221, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DescriptorBuilder.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterBuilderTest.java
- copied, changed from r1574221, sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/DescriptorBuilderTest.java
Removed:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DescriptorBuilder.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/DescriptorBuilderTest.java
Modified:
sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java?rev=1574562&r1=1574561&r2=1574562&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] Wed Mar 5 16:23:53 2014
@@ -454,11 +454,12 @@ public class ImmutableIdentifier extends
/**
* Organization or party responsible for definition and maintenance of the
- * {@linkplain #getCode code}.
+ * {@linkplain #getCode() code}.
*
- * @return The authority, or {@code null} if not available.
+ * <div class="note"><b>Example:</b> Coordinate Reference System (CRS) identified by an EPSG code will return
+ * {@link Citations#OGP}, since OGP is the organization maintaining the EPSG geodetic database.</div>
*
- * @see org.apache.sis.metadata.iso.citation.Citations#EPSG
+ * @return The authority, or {@code null} if not available.
*/
@Override
public Citation getAuthority() {
@@ -467,7 +468,7 @@ public class ImmutableIdentifier extends
/**
* Identifier of the version of the associated code space or code, as specified by the
- * code authority. This version is included only when the {@linkplain #getCode code}
+ * code authority. This version is included only when the {@linkplain #getCode() code}
* uses versions. When appropriate, the edition is identified by the effective date,
* coded using ISO 8601 date format.
*
Copied: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java (from r1574221, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DescriptorBuilder.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java?p2=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java&p1=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DescriptorBuilder.java&r1=1574221&r2=1574562&rev=1574562&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DescriptorBuilder.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java [UTF-8] Wed Mar 5 16:23:53 2014
@@ -16,36 +16,19 @@
*/
package org.apache.sis.parameter;
-import java.util.Map;
-import java.util.List;
-import java.util.HashMap;
-import java.util.ArrayList;
import javax.measure.unit.Unit;
-import org.opengis.util.NameSpace;
-import org.opengis.util.GenericName;
-import org.opengis.util.InternationalString;
-import org.opengis.metadata.citation.Citation;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
-import org.opengis.referencing.ReferenceIdentifier;
-import org.apache.sis.referencing.AbstractIdentifiedObject;
-import org.apache.sis.referencing.NamedIdentifier;
-import org.apache.sis.metadata.iso.ImmutableIdentifier;
-import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.measure.MeasurementRange;
import org.apache.sis.measure.NumberRange;
import org.apache.sis.measure.Range;
-import org.apache.sis.util.resources.Errors;
+import org.apache.sis.referencing.Builder;
import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
-import static org.apache.sis.internal.system.DefaultFactories.NAMES;
-
-// Related to JDK7
-import java.util.Objects;
/**
- * Provides convenience methods for easier {@link DefaultParameterDescriptor} instantiations.
+ * Provides convenience methods for easier {@code DefaultParameterDescriptor} instantiations.
* This builder can be helpful for map projection <em>providers</em>, or for implementation of
* any process that use parameters. Map projection or process <em>users</em> do not need this
* builder since they can invoke {@link ParameterDescriptor#createValue()} on the descriptor
@@ -62,7 +45,7 @@ import java.util.Objects;
*
* <p>Parameters can have at most one remark, which is specified by the {@code remarks(…)} method.</p>
*
- * <p>All the above-cited properties are cleared after a call to any {@code create(…)} method,
+ * <p>All the above-cited properties are cleared after a call to any {@code createXXX(…)} method,
* since those properties are specific to the each parameter. Other properties like codespace,
* version and cardinality are left unchanged because they may be shared by many parameters.</p>
*
@@ -74,45 +57,33 @@ import java.util.Objects;
* with no scale factor and no false easting/northing.
*
* {@preformat java
- * DescriptorBuilder builder = new DescriptorBuilder();
+ * ParameterBuilder builder = new ParameterBuilder();
* builder.codespace(Citations.OGP, "EPSG").mandatory();
* ParameterDescriptor<Double>[] parameters = {
- * builder.name("Latitude of natural origin") .createBounded( -80, +80, 0, NonSI.DEGREE_ANGLE),
- * builder.name("Longitude of natural origin") .createBounded(-180, +180, 0, NonSI.DEGREE_ANGLE),
- * builder.name("Scale factor at natural origin") .createStrictlyPositive(1, Unit.ONE),
- * builder.name("False easting") .create(0, SI.METRE),
- * builder.name("False northing") .create(0, SI.METRE)
+ * builder.name("Latitude of natural origin") .createBounded( -80, +84, 0, NonSI.DEGREE_ANGLE),
+ * builder.name("Longitude of natural origin") .createBounded(-180, +180, 0, NonSI.DEGREE_ANGLE),
+ * builder.name("Scale factor at natural origin").createStrictlyPositive(1, Unit.ONE),
+ * builder.name("False easting") .create(0, SI.METRE),
+ * builder.name("False northing") .create(0, SI.METRE)
* };
* }
*
+ * Note that different softwares or standards may use different names for the same parameters.
+ * Aliases may be defined to any parameters like below:
+ *
+ * {@preformat java
+ * builder.name("Longitude of natural origin") // Primary name in builder default namespace.
+ * .name(Citations.OGC, "central_meridian") // First alias in "OGC" namespace.
+ * .name(Citations.GEOTIFF, "NatOriginLong") // Second alias in "GeoTIFF" namespace.
+ * .createBounded(-80, +84, 0, NonSI.DEGREE_ANGLE);
+ * }
+ *
* @author Martin Desruisseaux (Geomatys)
* @since 0.4
* @version 0.4
* @module
*/
-public class DescriptorBuilder {
- /**
- * The name, alias, identifiers and remarks properties.
- */
- private final Map<String,Object> properties;
-
- /**
- * The aliases.
- */
- private final List<GenericName> aliases;
-
- /**
- * The identifiers.
- */
- private final List<ReferenceIdentifier> identifiers;
-
- /**
- * The codespace as a {@code NameSpace} object, or {@code null} if not yet created.
- *
- * @see #namespace()
- */
- private NameSpace namespace;
-
+public class ParameterBuilder extends Builder<ParameterBuilder> {
/**
* {@code true} if the parameter is mandatory, or {@code false} if optional.
*
@@ -124,294 +95,7 @@ public class DescriptorBuilder {
/**
* Creates a new builder.
*/
- public DescriptorBuilder() {
- properties = new HashMap<>(8);
- aliases = new ArrayList<>(4);
- identifiers = new ArrayList<>(4);
- }
-
- /**
- * Clears the identification information.
- * This does not clear the codespace, version and cardinality (mandatory versus optional) properties.
- */
- private void clearIdentification() {
- properties .put(ParameterDescriptor.NAME_KEY, null);
- properties .remove(ParameterDescriptor.REMARKS_KEY);
- aliases .clear();
- identifiers.clear();
- }
-
- /**
- * Sets the property value for the given key, if a change is still possible. The check for change permission
- * is needed for all keys defined in the {@link ReferenceIdentifier} interface. This check is not needed for
- * other keys, so callers do not need to invoke this method for other keys.
- *
- * @param key The key of the property to set.
- * @param value The value to set.
- * @return {@code true} if the property changed as a result of this method call.
- * @throws IllegalStateException if a new value is specified in a phase where the value can not be changed.
- */
- private boolean setProperty(final String key, final Object value) throws IllegalStateException {
- if (Objects.equals(properties.get(key), value)) {
- return false;
- }
- if (properties.get(ParameterDescriptor.NAME_KEY) != null) {
- throw new IllegalStateException(Errors.format(Errors.Keys.ValueAlreadyDefined_1, key));
- }
- properties.put(key, value);
- return true;
- }
-
- /**
- * Returns the namespace, creating it when first needed.
- */
- private NameSpace namespace() {
- if (namespace == null) {
- final String codespace = (String) properties.get(ReferenceIdentifier.CODESPACE_KEY);
- if (codespace != null) {
- namespace = NAMES.createNameSpace(NAMES.createLocalName(null, codespace), null);
- }
- }
- return namespace;
- }
-
- /**
- * Sets the authority and code space. This method is typically invoked only once, since
- * a group of parameters often uses the same code space for all individual parameters.
- *
- * <p><b>Condition:</b>
- * this method can not be invoked after one or more names or identifiers have been added (by calls to the
- * {@code name(…)} or {@code identifier(…)} methods) for the next descriptor to create. This method can be
- * invoked again after the name, aliases and identifiers have been cleared by a call to {@code createXXX(…)}.</p>
- *
- * <p><b>Life cycle:</b>
- * this property is kept unchanged until this {@code codespace(…)} method is invoked again.</p>
- *
- * @param authority Bibliographic reference to the authority defining the codes, or {@code null} if none.
- * @param codespace The parameter codespace, or {@code null} for inferring it from the authority.
- * @return {@code this}, for method call chaining.
- * @throws IllegalStateException if {@code name(…)} or {@code identifier(…)} has been invoked at least
- * once since builder construction or since the last call to a {@code createXXX(…)} method.
- */
- public DescriptorBuilder codespace(final Citation authority, final String codespace) {
- if (!setProperty(ReferenceIdentifier.CODESPACE_KEY, codespace)) {
- namespace = null;
- }
- setProperty(ReferenceIdentifier.AUTHORITY_KEY, authority);
- return this;
- }
-
- /**
- * Sets the version of parameter definitions. This method is typically invoked only once,
- * since a group of parameters often uses the same version for all individual parameters.
- *
- * <p><b>Condition:</b>
- * this method can not be invoked after one or more names or identifiers have been added (by calls to the
- * {@code name(…)} or {@code identifier(…)} methods) for the next descriptor to create. This method can be
- * invoked again after the name, aliases and identifiers have been cleared by a call to {@code createXXX(…)}.</p>
- *
- * <p><b>Life cycle:</b>
- * this property is kept unchanged until this {@code version(…)} method is invoked again.</p>
- *
- * @param version The version of code definitions, or {@code null} if none.
- * @return {@code this}, for method call chaining.
- * @throws IllegalStateException if {@code name(…)} or {@code identifier(…)} has been invoked at least
- * once since builder construction or since the last call to a {@code createXXX(…)} method.
- */
- public DescriptorBuilder version(final String version) {
- setProperty(ReferenceIdentifier.VERSION_KEY, version);
- return this;
- }
-
- /**
- * Adds a parameter name given by a {@code String} or {@code InternationalString}.
- * The given string will be combined with the authority, {@linkplain #codespace(Citation, String) code space}
- * and {@linkplain #version(String) version} information for creating the {@link ReferenceIdentifier} or
- * {@link GenericName} object.
- *
- * {@section Name and aliases}
- * This method can be invoked many times. The first invocation sets the
- * {@linkplain AbstractIdentifiedObject#getName() primary name}, and
- * all subsequent invocations add an {@linkplain AbstractIdentifiedObject#getAlias() alias}.
- *
- * <p><b>Life cycle:</b>
- * the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
- *
- * @param name The parameter name.
- * @return {@code this}, for method call chaining.
- */
- public DescriptorBuilder name(final CharSequence name) {
- ensureNonNull("name", name);
- final Object old = properties.put(ParameterDescriptor.NAME_KEY, name.toString());
- if (old != null) {
- properties.put(ParameterDescriptor.NAME_KEY, old); // Restore previous value.
- aliases.add(name instanceof GenericName ? (GenericName) name : NAMES.createLocalName(namespace(), name));
- }
- return this;
- }
-
- /**
- * Adds a parameter name in an alternative namespace. This method is typically invoked for
- * {@linkplain AbstractIdentifiedObject#getAlias() aliases} defined after the primary name.
- *
- * <div class="note"><b>Example:</b>
- * The "<cite>Longitude of natural origin</cite>" parameter defined by EPSG is named differently
- * by OGC and GeoTIFF. Those alternative names can be defined as below:
- *
- * {@preformat java
- * builder.name("Longitude of natural origin") // Primary name in builder default namespace.
- * .name(Citations.OGC, "central_meridian") // First alias in "OGC" namespace.
- * .name(Citations.GEOTIFF, "NatOriginLong"); // Second alias in "GeoTIFF" namespace.
- * }
- *
- * In this example, {@code "central_meridian"} will be the
- * {@linkplain org.apache.sis.util.iso.DefaultScopedName#tip() tip} and {@code "OGC"} will be the
- * {@linkplain org.apache.sis.util.iso.DefaultScopedName#head() head} of the first alias.</div>
- *
- * <p><b>Life cycle:</b>
- * the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
- *
- * @param authority Bibliographic reference to the authority defining the codes, or {@code null} if none.
- * @param name The parameter alias as a name in the namespace of the given authority.
- * @return {@code this}, for method call chaining.
- *
- * @see #identifier(Citation, String)
- */
- public DescriptorBuilder name(final Citation authority, final CharSequence name) {
- ensureNonNull("name", name);
- final NamedIdentifier identifier;
- if (name instanceof InternationalString) {
- identifier = new NamedIdentifier(authority, (InternationalString) name);
- } else {
- identifier = new NamedIdentifier(authority, name.toString());
- }
- final Object old = properties.put(ParameterDescriptor.NAME_KEY, identifier);
- if (old != null) {
- properties.put(ParameterDescriptor.NAME_KEY, old); // Restore previous value.
- aliases.add(identifier);
- }
- return this;
- }
-
- /**
- * Adds a parameter name fully specified by the given identifier.
- * This method ignores the authority, {@linkplain #codespace(Citation, String) code space} or
- * {@linkplain #version(String) version} specified to this builder (if any), since the given
- * identifier already contains those information.
- *
- * {@section Name and aliases}
- * This method can be invoked many times. The first invocation sets the
- * {@linkplain AbstractIdentifiedObject#getName() primary name} to the given value, and
- * all subsequent invocations add an {@linkplain AbstractIdentifiedObject#getAlias() alias}.
- *
- * <p><b>Life cycle:</b>
- * the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
- *
- * @param name The parameter name as an identifier.
- * @return {@code this}, for method call chaining.
- */
- public DescriptorBuilder name(final ReferenceIdentifier name) {
- ensureNonNull("name", name);
- final Object old = properties.put(ParameterDescriptor.NAME_KEY, name);
- if (old != null) {
- properties.put(ParameterDescriptor.NAME_KEY, old); // Restore previous value.
- aliases.add(name instanceof GenericName ? (GenericName) name : new NamedIdentifier(name));
- }
- return this;
- }
-
- /**
- * Adds a parameter name fully specified by the given generic name.
- * This method ignores the authority, {@linkplain #codespace(Citation, String) code space} or
- * {@linkplain #version(String) version} specified to this builder (if any), since the given
- * generic name already contains those information.
- *
- * {@section Name and aliases}
- * This method can be invoked many times. The first invocation sets the
- * {@linkplain AbstractIdentifiedObject#getName() primary name} to the given value, and
- * all subsequent invocations add an {@linkplain AbstractIdentifiedObject#getAlias() alias}.
- *
- * <p><b>Life cycle:</b>
- * the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
- *
- * @param name The parameter name as an identifier.
- * @return {@code this}, for method call chaining.
- */
- public DescriptorBuilder name(final GenericName name) {
- ensureNonNull("name", name);
- if (properties.get(ParameterDescriptor.NAME_KEY) == null) {
- properties.put(ParameterDescriptor.NAME_KEY, new NamedIdentifier(name));
- } else {
- aliases.add(name);
- }
- return this;
- }
-
- /**
- * Adds a parameter identifier given by a {@code String}.
- * The given string will be combined with the authority, {@linkplain #codespace(Citation, String) code space}
- * and {@linkplain #version(String) version} information for creating the {@link ReferenceIdentifier} object.
- *
- * <p><b>Life cycle:</b>
- * all identifiers are cleared after a {@code createXXX(…)} method has been invoked.</p>
- *
- * @param identifier The parameter identifier.
- * @return {@code this}, for method call chaining.
- */
- public DescriptorBuilder identifier(final String identifier) {
- ensureNonNull("identifier", identifier);
- identifiers.add(new ImmutableIdentifier((Citation) properties.get(ReferenceIdentifier.AUTHORITY_KEY),
- (String) properties.get(ReferenceIdentifier.CODESPACE_KEY), identifier));
- return this;
- }
-
- /**
- * Adds a parameter identifier in an alternative namespace. This method is typically invoked in
- * complement to {@link #name(Citation, CharSequence)}.
- *
- * <p><b>Life cycle:</b>
- * all identifiers are cleared after a {@code createXXX(…)} method has been invoked.</p>
- *
- * @param authority Bibliographic reference to the authority defining the codes, or {@code null} if none.
- * @param identifier The parameter identifier as a code in the namespace of the given authority.
- * @return {@code this}, for method call chaining.
- *
- * @see #name(Citation, CharSequence)
- */
- public DescriptorBuilder identifier(final Citation authority, final String identifier) {
- ensureNonNull("identifier", identifier);
- identifiers.add(new ImmutableIdentifier(authority, Citations.getIdentifier(authority), identifier));
- return this;
- }
-
- /**
- * Adds a parameter identifier fully specified by the given identifier.
- * This method ignores the authority, {@linkplain #codespace(Citation, String) code space} or
- * {@linkplain #version(String) version} specified to this builder (if any), since the given
- * identifier already contains those information.
- *
- * <p><b>Life cycle:</b>
- * all identifiers are cleared after a {@code createXXX(…)} method has been invoked.</p>
- *
- * @param identifier The parameter identifier.
- * @return {@code this}, for method call chaining.
- */
- public DescriptorBuilder identifier(final ReferenceIdentifier identifier) {
- ensureNonNull("identifier", identifier);
- identifiers.add(identifier);
- return this;
- }
-
- /**
- * Sets remarks as a {@code String} or {@code InternationalString} instance.
- * Calls to this method overwrite any previous value.
- *
- * @param remarks The remarks, or {@code null} if none.
- * @return {@code this}, for method call chaining.
- */
- public DescriptorBuilder remarks(final CharSequence remarks) {
- properties.put(ParameterDescriptor.REMARKS_KEY, remarks);
- return this;
+ public ParameterBuilder() {
}
/**
@@ -420,7 +104,7 @@ public class DescriptorBuilder {
*
* @return {@code this}, for method call chaining.
*/
- public DescriptorBuilder mandatory() {
+ public ParameterBuilder mandatory() {
this.required = true;
return this;
}
@@ -431,7 +115,7 @@ public class DescriptorBuilder {
*
* @return {@code this}, for method call chaining.
*/
- public DescriptorBuilder optional() {
+ public ParameterBuilder optional() {
this.required = false;
return this;
}
@@ -536,6 +220,22 @@ public class DescriptorBuilder {
}
/**
+ * Creates a descriptor for values in the domain represented by the given {@code Range} object.
+ * This method allows to specify whether the minimum and maximum values are inclusive or not.
+ *
+ * @param <T> The type of the parameter values.
+ * @param valueDomain The minimum value, maximum value and unit of measurement.
+ * @param defaultValue The default value for the parameter, or {@code null} if none.
+ * @return The parameter descriptor for the given domain of values.
+ */
+ public <T extends Comparable<? super T>> ParameterDescriptor<T> createBounded(
+ final Range<T> valueDomain, final T defaultValue)
+ {
+ ensureNonNull("valueDomain", valueDomain);
+ return create(valueDomain.getElementType(), valueDomain, null, defaultValue);
+ }
+
+ /**
* Creates a descriptor for a parameter restricted to a set of valid values.
* The descriptor has no minimal or maximal value and no unit.
*
@@ -551,21 +251,21 @@ public class DescriptorBuilder {
* @return The parameter descriptor for the given set of valid values.
*/
public <T> ParameterDescriptor<T> createEnumerated(final Class<T> valueClass, final T[] validValues, final T defaultValue) {
+ ensureNonNull("valueClass", valueClass);
return create(valueClass, null, validValues, defaultValue);
}
/**
- * Invoked by all {@code createXXX(…)} method for creating the descriptor from the properties currently set
- * in this builder.
+ * Invoked by all {@code createXXX(…)} methods for creating the descriptor from the properties
+ * currently set in this builder. Identification information are cleared after this method call.
*/
private <T> ParameterDescriptor<T> create(final Class<T> valueClass, final Range<?> valueDomain,
final T[] validValues, final T defaultValue)
{
- properties.put(ParameterDescriptor.ALIAS_KEY, aliases.toArray(new GenericName[aliases.size()]));
- properties.put(ParameterDescriptor.IDENTIFIERS_KEY, identifiers.toArray(new ReferenceIdentifier[identifiers.size()]));
+ onCreate(false);
final ParameterDescriptor<T> descriptor = new DefaultParameterDescriptor<>(
properties, valueClass, valueDomain, validValues, defaultValue, required);
- clearIdentification();
+ onCreate(true);
return descriptor;
}
}
Copied: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java (from r1574221, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DescriptorBuilder.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java?p2=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java&p1=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DescriptorBuilder.java&r1=1574221&r2=1574562&rev=1574562&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/DescriptorBuilder.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java [UTF-8] Wed Mar 5 16:23:53 2014
@@ -14,27 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sis.parameter;
+package org.apache.sis.referencing;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.ArrayList;
-import javax.measure.unit.Unit;
+import java.lang.reflect.Type;
+import java.lang.reflect.ParameterizedType;
import org.opengis.util.NameSpace;
import org.opengis.util.GenericName;
import org.opengis.util.InternationalString;
import org.opengis.metadata.citation.Citation;
-import org.opengis.parameter.ParameterDescriptor;
-import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.ReferenceIdentifier;
-import org.apache.sis.referencing.AbstractIdentifiedObject;
-import org.apache.sis.referencing.NamedIdentifier;
import org.apache.sis.metadata.iso.ImmutableIdentifier;
import org.apache.sis.metadata.iso.citation.Citations;
-import org.apache.sis.measure.MeasurementRange;
-import org.apache.sis.measure.NumberRange;
-import org.apache.sis.measure.Range;
import org.apache.sis.util.resources.Errors;
import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
@@ -45,64 +40,100 @@ import java.util.Objects;
/**
- * Provides convenience methods for easier {@link DefaultParameterDescriptor} instantiations.
- * This builder can be helpful for map projection <em>providers</em>, or for implementation of
- * any process that use parameters. Map projection or process <em>users</em> do not need this
- * builder since they can invoke {@link ParameterDescriptor#createValue()} on the descriptor
- * provided by the implementor.
- *
- * {@section Identification properties}
- * Each parameter must have a name, which can be specified by any of the {@code name(…)} methods.
- * Parameters can optionally have an arbitrary amount of aliases, which are also specified by the
- * {@code name(…)} methods — each call after the first one adds an alias.
- *
- * <p>Parameters can also have an arbitrary amount of identifiers, which are specified by the
- * {@code identifier(…)} methods. Like names, more than one identifier can be added by invoking
- * the method many time.</p>
- *
- * <p>Parameters can have at most one remark, which is specified by the {@code remarks(…)} method.</p>
- *
- * <p>All the above-cited properties are cleared after a call to any {@code create(…)} method,
- * since those properties are specific to the each parameter. Other properties like codespace,
- * version and cardinality are left unchanged because they may be shared by many parameters.</p>
- *
- * {@section Usage example}
- * Parameter descriptors are typically grouped in a {@link ParameterDescriptorGroup}.
- * All parameters usually have the same namespace, which can be declared only once.
- * The following example creates parameters for "<cite>Mercator (variant A)</cite>" projection method (EPSG:9804)
- * with all parameter names in the "EPSG" namespace. The default values define a projection centered on (0°,0°)
- * with no scale factor and no false easting/northing.
+ * Base class of builders for various kind of {@code IdentifiedObject}. {@code Builder}s aim to make object
+ * creation easier — they do not add any new functionality to {@link org.opengis.referencing.ObjectFactory}.
+ * Builder methods like {@link #name(CharSequence)} and {@link #identifier(String)} provide convenient ways
+ * to fill the {@link #properties} map, which will be given to the {@code ObjectFactory} methods at
+ * {@code IdentifiedObject} creation time. Creations happen when any {@code createXXX(…)} method defined in
+ * the builder subclasses is invoked.
*
+ * <p>This base class provides method for defining the following {@link IdentifiedObject} properties:</p>
+ * <ul>
+ * <li><p><b>{@link AbstractIdentifiedObject#getName() Name}:</b><br>
+ * Each {@code IdentifiedObject} must have a name, which can be specified by a call to any of the
+ * {@code name(…)} methods defined in this class.</p></li>
+ *
+ * <li><p><b>{@link AbstractIdentifiedObject#getAlias() Aliases}:</b><br>
+ * Identified objects can optionally have an arbitrary amount of aliases, which are also specified
+ * by the {@code name(…)} methods — each call after the first one adds an alias.</p></li>
+ *
+ * <li><p><b>{@link AbstractIdentifiedObject#getIdentifiers() Identifiers}:</b><br>
+ * Identified objects can also have an arbitrary amount of identifiers, which are specified by the
+ * {@code identifier(…)} methods. Like names, more than one identifier can be added by invoking
+ * the method many time.</p></li>
+ *
+ * <li><p><b>{@link AbstractIdentifiedObject#getRemarks() Remarks}:</b><br>
+ * Identified objects can have at most one remark, which is specified by the {@code remarks(…)} method.</p></li>
+ * </ul>
+ *
+ * {@section Builder property lifetimes}
+ * The same builder can be used for creating many objects, since constructing a Coordinate Reference System (CRS)
+ * may require constructing many components (coordinate system, datum, ellipsoid, prime meridian, <i>etc.</i>),
+ * some of them sharing common properties. In order to simplify the most common usage scenarios, identification
+ * properties have two different lifetimes in the {@code Builder} class:
+ *
+ * <ul>
+ * <li>{@linkplain NamedIdentifier#getAuthority() Authority}, {@linkplain NamedIdentifier#getCodeSpace() code space}
+ * and {@linkplain NamedIdentifier#getVersion() version} information specified to this {@code Builder} will stay
+ * active until they are specified again, because those information are typically shared by all components.</li>
+ * <li>Other properties (name, aliases, identifiers and remarks) are cleared after each call to a {@code createXXX(…)}
+ * method, because they are usually specific to a particular {@code IdentifiedObject} instance.</li>
+ * </ul>
+ *
+ *
+ * <div class="note"><b>Note for subclass implementors:</b>
+ * <ul>
+ * <li>The type {@code <B>} shall be exactly the subclass type.
+ * For performance reasons, this is verified only if Java assertions are enabled.</li>
+ * <li>All {@code createXXX(…)} methods shall invoke {@link #onCreate(boolean)} before and after
+ * usage of {@link #properties} map by the factory.</li>
+ * </ul>
+ *
+ * <b>Example:</b>
* {@preformat java
- * DescriptorBuilder builder = new DescriptorBuilder();
- * builder.codespace(Citations.OGP, "EPSG").mandatory();
- * ParameterDescriptor<Double>[] parameters = {
- * builder.name("Latitude of natural origin") .createBounded( -80, +80, 0, NonSI.DEGREE_ANGLE),
- * builder.name("Longitude of natural origin") .createBounded(-180, +180, 0, NonSI.DEGREE_ANGLE),
- * builder.name("Scale factor at natural origin") .createStrictlyPositive(1, Unit.ONE),
- * builder.name("False easting") .create(0, SI.METRE),
- * builder.name("False northing") .create(0, SI.METRE)
- * };
+ * public class MyBuilder extends Builder<MyBuilder> {
+ * public Foo createFoo() {
+ * onCreate(false);
+ * Foo foo = factory.createFoo(properties);
+ * onCreate(true);
+ * return foo;
+ * }
+ * }
* }
+ * </div>
+ *
+ * @param <B> The builder subclass.
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.4
* @version 0.4
* @module
*/
-public class DescriptorBuilder {
+public abstract class Builder<B extends Builder<B>> {
/**
- * The name, alias, identifiers and remarks properties.
+ * The properties to be given to {@link org.opengis.referencing.ObjectFactory} methods.
+ * This map may contain values for the
+ * {@value org.opengis.referencing.IdentifiedObject#NAME_KEY},
+ * {@value org.opengis.referencing.IdentifiedObject#ALIAS_KEY},
+ * {@value org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY} and
+ * {@value org.opengis.referencing.IdentifiedObject#REMARKS_KEY} keys.
+ * Subclasses may add other entries like
+ * {@value org.opengis.referencing.ReferenceSystem#DOMAIN_OF_VALIDITY_KEY},
+ * {@value org.opengis.referencing.ReferenceSystem#SCOPE_KEY} keys.
+ *
+ * <p>See <cite>Notes for subclass implementors</cite> in class javadoc for usage conditions.</p>
+ *
+ * @see #onCreate(boolean)
*/
- private final Map<String,Object> properties;
+ protected final Map<String,Object> properties;
/**
- * The aliases.
+ * A temporary list for aliases, before to assign them to the {@link #properties}.
*/
private final List<GenericName> aliases;
/**
- * The identifiers.
+ * A temporary list for identifiers, before to assign them to the {@link #properties}.
*/
private final List<ReferenceIdentifier> identifiers;
@@ -114,31 +145,43 @@ public class DescriptorBuilder {
private NameSpace namespace;
/**
- * {@code true} if the parameter is mandatory, or {@code false} if optional.
- *
- * @see #mandatory()
- * @see #optional()
- */
- private boolean required;
-
- /**
* Creates a new builder.
*/
- public DescriptorBuilder() {
+ protected Builder() {
+ assert isSelf(getClass());
properties = new HashMap<>(8);
aliases = new ArrayList<>(4);
identifiers = new ArrayList<>(4);
}
/**
- * Clears the identification information.
- * This does not clear the codespace, version and cardinality (mandatory versus optional) properties.
+ * Verifies that {@code B} in {@code <B extends Builder<B>} is the expected class.
+ * This method is for assertion purposes only.
*/
- private void clearIdentification() {
- properties .put(ParameterDescriptor.NAME_KEY, null);
- properties .remove(ParameterDescriptor.REMARKS_KEY);
- aliases .clear();
- identifiers.clear();
+ private static boolean isSelf(final Class<?> expected) {
+ for (Class<?> c = expected; c != null; c = c.getSuperclass()) {
+ Type type = c.getGenericSuperclass();
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType p = (ParameterizedType) type;
+ if (p.getRawType() == Builder.class) {
+ type = p.getActualTypeArguments()[0];
+ if (type == expected) return true;
+ throw new AssertionError(type);
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns {@code this} casted to {@code <B>}. The cast is valid if the assertion performed
+ * at construction time passes. Since the {@code <B>} type is hard-coded in the source code,
+ * if the JUnit test passes then the cast should always be valid for all instances of the
+ * same builder class.
+ */
+ @SuppressWarnings("unchecked")
+ private B self() {
+ return (B) this;
}
/**
@@ -155,7 +198,7 @@ public class DescriptorBuilder {
if (Objects.equals(properties.get(key), value)) {
return false;
}
- if (properties.get(ParameterDescriptor.NAME_KEY) != null) {
+ if (properties.get(IdentifiedObject.NAME_KEY) != null) {
throw new IllegalStateException(Errors.format(Errors.Keys.ValueAlreadyDefined_1, key));
}
properties.put(key, value);
@@ -176,41 +219,41 @@ public class DescriptorBuilder {
}
/**
- * Sets the authority and code space. This method is typically invoked only once, since
- * a group of parameters often uses the same code space for all individual parameters.
+ * Sets the {@code ReferenceIdentifier} authority and code space. This method is typically invoked only once,
+ * since a compound object often uses the same code space for all individual components.
*
* <p><b>Condition:</b>
* this method can not be invoked after one or more names or identifiers have been added (by calls to the
- * {@code name(…)} or {@code identifier(…)} methods) for the next descriptor to create. This method can be
+ * {@code name(…)} or {@code identifier(…)} methods) for the next object to create. This method can be
* invoked again after the name, aliases and identifiers have been cleared by a call to {@code createXXX(…)}.</p>
*
- * <p><b>Life cycle:</b>
+ * <p><b>Lifetime:</b>
* this property is kept unchanged until this {@code codespace(…)} method is invoked again.</p>
*
* @param authority Bibliographic reference to the authority defining the codes, or {@code null} if none.
- * @param codespace The parameter codespace, or {@code null} for inferring it from the authority.
+ * @param codespace The {@code IdentifiedObject} codespace, or {@code null} for inferring it from the authority.
* @return {@code this}, for method call chaining.
* @throws IllegalStateException if {@code name(…)} or {@code identifier(…)} has been invoked at least
* once since builder construction or since the last call to a {@code createXXX(…)} method.
*/
- public DescriptorBuilder codespace(final Citation authority, final String codespace) {
+ public B codespace(final Citation authority, final String codespace) {
if (!setProperty(ReferenceIdentifier.CODESPACE_KEY, codespace)) {
namespace = null;
}
setProperty(ReferenceIdentifier.AUTHORITY_KEY, authority);
- return this;
+ return self();
}
/**
- * Sets the version of parameter definitions. This method is typically invoked only once,
- * since a group of parameters often uses the same version for all individual parameters.
+ * Sets the {@code ReferenceIdentifier} version of object definitions. This method is typically invoked only once,
+ * since a compound object often uses the same version for all individual components.
*
* <p><b>Condition:</b>
* this method can not be invoked after one or more names or identifiers have been added (by calls to the
- * {@code name(…)} or {@code identifier(…)} methods) for the next descriptor to create. This method can be
+ * {@code name(…)} or {@code identifier(…)} methods) for the next object to create. This method can be
* invoked again after the name, aliases and identifiers have been cleared by a call to {@code createXXX(…)}.</p>
*
- * <p><b>Life cycle:</b>
+ * <p><b>Lifetime:</b>
* this property is kept unchanged until this {@code version(…)} method is invoked again.</p>
*
* @param version The version of code definitions, or {@code null} if none.
@@ -218,13 +261,13 @@ public class DescriptorBuilder {
* @throws IllegalStateException if {@code name(…)} or {@code identifier(…)} has been invoked at least
* once since builder construction or since the last call to a {@code createXXX(…)} method.
*/
- public DescriptorBuilder version(final String version) {
+ public B version(final String version) {
setProperty(ReferenceIdentifier.VERSION_KEY, version);
- return this;
+ return self();
}
/**
- * Adds a parameter name given by a {@code String} or {@code InternationalString}.
+ * Adds an {@code IdentifiedObject} name given by a {@code String} or {@code InternationalString}.
* The given string will be combined with the authority, {@linkplain #codespace(Citation, String) code space}
* and {@linkplain #version(String) version} information for creating the {@link ReferenceIdentifier} or
* {@link GenericName} object.
@@ -234,24 +277,24 @@ public class DescriptorBuilder {
* {@linkplain AbstractIdentifiedObject#getName() primary name}, and
* all subsequent invocations add an {@linkplain AbstractIdentifiedObject#getAlias() alias}.
*
- * <p><b>Life cycle:</b>
+ * <p><b>Lifetime:</b>
* the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
*
- * @param name The parameter name.
+ * @param name The {@code IdentifiedObject} name.
* @return {@code this}, for method call chaining.
*/
- public DescriptorBuilder name(final CharSequence name) {
+ public B name(final CharSequence name) {
ensureNonNull("name", name);
- final Object old = properties.put(ParameterDescriptor.NAME_KEY, name.toString());
+ final Object old = properties.put(IdentifiedObject.NAME_KEY, name.toString());
if (old != null) {
- properties.put(ParameterDescriptor.NAME_KEY, old); // Restore previous value.
+ properties.put(IdentifiedObject.NAME_KEY, old); // Restore previous value.
aliases.add(name instanceof GenericName ? (GenericName) name : NAMES.createLocalName(namespace(), name));
}
- return this;
+ return self();
}
/**
- * Adds a parameter name in an alternative namespace. This method is typically invoked for
+ * Adds an {@code IdentifiedObject} name in an alternative namespace. This method is typically invoked for
* {@linkplain AbstractIdentifiedObject#getAlias() aliases} defined after the primary name.
*
* <div class="note"><b>Example:</b>
@@ -259,7 +302,8 @@ public class DescriptorBuilder {
* by OGC and GeoTIFF. Those alternative names can be defined as below:
*
* {@preformat java
- * builder.name("Longitude of natural origin") // Primary name in builder default namespace.
+ * builder.codespace(Citations.OGP, "EPSG") // Sets the default namespace to "EPSG".
+ * .name("Longitude of natural origin") // Primary name in builder default namespace.
* .name(Citations.OGC, "central_meridian") // First alias in "OGC" namespace.
* .name(Citations.GEOTIFF, "NatOriginLong"); // Second alias in "GeoTIFF" namespace.
* }
@@ -268,16 +312,16 @@ public class DescriptorBuilder {
* {@linkplain org.apache.sis.util.iso.DefaultScopedName#tip() tip} and {@code "OGC"} will be the
* {@linkplain org.apache.sis.util.iso.DefaultScopedName#head() head} of the first alias.</div>
*
- * <p><b>Life cycle:</b>
+ * <p><b>Lifetime:</b>
* the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
*
* @param authority Bibliographic reference to the authority defining the codes, or {@code null} if none.
- * @param name The parameter alias as a name in the namespace of the given authority.
+ * @param name The {@code IdentifiedObject} alias as a name in the namespace of the given authority.
* @return {@code this}, for method call chaining.
*
* @see #identifier(Citation, String)
*/
- public DescriptorBuilder name(final Citation authority, final CharSequence name) {
+ public B name(final Citation authority, final CharSequence name) {
ensureNonNull("name", name);
final NamedIdentifier identifier;
if (name instanceof InternationalString) {
@@ -285,16 +329,16 @@ public class DescriptorBuilder {
} else {
identifier = new NamedIdentifier(authority, name.toString());
}
- final Object old = properties.put(ParameterDescriptor.NAME_KEY, identifier);
+ final Object old = properties.put(IdentifiedObject.NAME_KEY, identifier);
if (old != null) {
- properties.put(ParameterDescriptor.NAME_KEY, old); // Restore previous value.
+ properties.put(IdentifiedObject.NAME_KEY, old); // Restore previous value.
aliases.add(identifier);
}
- return this;
+ return self();
}
/**
- * Adds a parameter name fully specified by the given identifier.
+ * Adds an {@code IdentifiedObject} name fully specified by the given identifier.
* This method ignores the authority, {@linkplain #codespace(Citation, String) code space} or
* {@linkplain #version(String) version} specified to this builder (if any), since the given
* identifier already contains those information.
@@ -304,24 +348,24 @@ public class DescriptorBuilder {
* {@linkplain AbstractIdentifiedObject#getName() primary name} to the given value, and
* all subsequent invocations add an {@linkplain AbstractIdentifiedObject#getAlias() alias}.
*
- * <p><b>Life cycle:</b>
+ * <p><b>Lifetime:</b>
* the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
*
- * @param name The parameter name as an identifier.
+ * @param name The {@code IdentifiedObject} name as an identifier.
* @return {@code this}, for method call chaining.
*/
- public DescriptorBuilder name(final ReferenceIdentifier name) {
+ public B name(final ReferenceIdentifier name) {
ensureNonNull("name", name);
- final Object old = properties.put(ParameterDescriptor.NAME_KEY, name);
+ final Object old = properties.put(IdentifiedObject.NAME_KEY, name);
if (old != null) {
- properties.put(ParameterDescriptor.NAME_KEY, old); // Restore previous value.
+ properties.put(IdentifiedObject.NAME_KEY, old); // Restore previous value.
aliases.add(name instanceof GenericName ? (GenericName) name : new NamedIdentifier(name));
}
- return this;
+ return self();
}
/**
- * Adds a parameter name fully specified by the given generic name.
+ * Adds an {@code IdentifiedObject} name fully specified by the given generic name.
* This method ignores the authority, {@linkplain #codespace(Citation, String) code space} or
* {@linkplain #version(String) version} specified to this builder (if any), since the given
* generic name already contains those information.
@@ -331,241 +375,123 @@ public class DescriptorBuilder {
* {@linkplain AbstractIdentifiedObject#getName() primary name} to the given value, and
* all subsequent invocations add an {@linkplain AbstractIdentifiedObject#getAlias() alias}.
*
- * <p><b>Life cycle:</b>
+ * <p><b>Lifetime:</b>
* the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
*
- * @param name The parameter name as an identifier.
+ * @param name The {@code IdentifiedObject} name as an identifier.
* @return {@code this}, for method call chaining.
*/
- public DescriptorBuilder name(final GenericName name) {
+ public B name(final GenericName name) {
ensureNonNull("name", name);
- if (properties.get(ParameterDescriptor.NAME_KEY) == null) {
- properties.put(ParameterDescriptor.NAME_KEY, new NamedIdentifier(name));
+ if (properties.get(IdentifiedObject.NAME_KEY) == null) {
+ properties.put(IdentifiedObject.NAME_KEY, new NamedIdentifier(name));
} else {
aliases.add(name);
}
- return this;
+ return self();
}
/**
- * Adds a parameter identifier given by a {@code String}.
+ * Adds an {@code IdentifiedObject} identifier given by a {@code String}.
* The given string will be combined with the authority, {@linkplain #codespace(Citation, String) code space}
* and {@linkplain #version(String) version} information for creating the {@link ReferenceIdentifier} object.
*
- * <p><b>Life cycle:</b>
+ * <p><b>Lifetime:</b>
* all identifiers are cleared after a {@code createXXX(…)} method has been invoked.</p>
*
- * @param identifier The parameter identifier.
+ * @param identifier The {@code IdentifiedObject} identifier.
* @return {@code this}, for method call chaining.
*/
- public DescriptorBuilder identifier(final String identifier) {
+ public B identifier(final String identifier) {
ensureNonNull("identifier", identifier);
identifiers.add(new ImmutableIdentifier((Citation) properties.get(ReferenceIdentifier.AUTHORITY_KEY),
(String) properties.get(ReferenceIdentifier.CODESPACE_KEY), identifier));
- return this;
+ return self();
}
/**
- * Adds a parameter identifier in an alternative namespace. This method is typically invoked in
- * complement to {@link #name(Citation, CharSequence)}.
+ * Adds an {@code IdentifiedObject} identifier in an alternative namespace.
+ * This method is typically invoked in complement to {@link #name(Citation, CharSequence)}.
*
- * <p><b>Life cycle:</b>
+ * <p><b>Lifetime:</b>
* all identifiers are cleared after a {@code createXXX(…)} method has been invoked.</p>
*
* @param authority Bibliographic reference to the authority defining the codes, or {@code null} if none.
- * @param identifier The parameter identifier as a code in the namespace of the given authority.
+ * @param identifier The {@code IdentifiedObject} identifier as a code in the namespace of the given authority.
* @return {@code this}, for method call chaining.
*
* @see #name(Citation, CharSequence)
*/
- public DescriptorBuilder identifier(final Citation authority, final String identifier) {
+ public B identifier(final Citation authority, final String identifier) {
ensureNonNull("identifier", identifier);
identifiers.add(new ImmutableIdentifier(authority, Citations.getIdentifier(authority), identifier));
- return this;
+ return self();
}
/**
- * Adds a parameter identifier fully specified by the given identifier.
+ * Adds an {@code IdentifiedObject} identifier fully specified by the given identifier.
* This method ignores the authority, {@linkplain #codespace(Citation, String) code space} or
* {@linkplain #version(String) version} specified to this builder (if any), since the given
* identifier already contains those information.
*
- * <p><b>Life cycle:</b>
+ * <p><b>Lifetime:</b>
* all identifiers are cleared after a {@code createXXX(…)} method has been invoked.</p>
*
- * @param identifier The parameter identifier.
+ * @param identifier The {@code IdentifiedObject} identifier.
* @return {@code this}, for method call chaining.
*/
- public DescriptorBuilder identifier(final ReferenceIdentifier identifier) {
+ public B identifier(final ReferenceIdentifier identifier) {
ensureNonNull("identifier", identifier);
identifiers.add(identifier);
- return this;
+ return self();
}
/**
* Sets remarks as a {@code String} or {@code InternationalString} instance.
* Calls to this method overwrite any previous value.
*
- * @param remarks The remarks, or {@code null} if none.
- * @return {@code this}, for method call chaining.
- */
- public DescriptorBuilder remarks(final CharSequence remarks) {
- properties.put(ParameterDescriptor.REMARKS_KEY, remarks);
- return this;
- }
-
- /**
- * Sets the parameter as mandatory.
- * The minimum number of times that values are required will be 1.
- *
- * @return {@code this}, for method call chaining.
- */
- public DescriptorBuilder mandatory() {
- this.required = true;
- return this;
- }
-
- /**
- * Sets the parameter as optional.
- * The minimum number of times that values are required will be 0.
+ * <p><b>Lifetime:</b>
+ * previous remarks are discarded by calls to {@code remarks(…)}.
+ * Remarks are cleared after a {@code createXXX(…)} method has been invoked.</p>
*
+ * @param remarks The remarks, or {@code null} if none.
* @return {@code this}, for method call chaining.
*/
- public DescriptorBuilder optional() {
- this.required = false;
- return this;
+ public B remarks(final CharSequence remarks) {
+ properties.put(IdentifiedObject.REMARKS_KEY, remarks);
+ return self();
}
/**
- * Creates a descriptor for floating point values without domain restriction.
- * All {@code double} values are considered valid.
+ * Initializes/cleanups the {@link #properties} map before/after a {@code createXXX(…)} execution.
+ * Subclasses shall invoke this method in their {@code createXXX(…)} methods as below:
*
- * @param defaultValue The default value for the parameter, or {@link Double#NaN} if none.
- * @param unit The default unit, or {@code null} if none.
- * @return The parameter descriptor for the given default value and unit.
- */
- public ParameterDescriptor<Double> create(final double defaultValue, final Unit<?> unit) {
- final Range<Double> valueDomain;
- if (unit != null) {
- valueDomain = MeasurementRange.create(Double.NEGATIVE_INFINITY, false, Double.POSITIVE_INFINITY, false, unit);
- } else {
- valueDomain = null;
- }
- return create(Double.class, valueDomain, null, Double.valueOf(defaultValue));
- }
-
- /**
- * Creates a descriptor for floating point values greater than zero.
- * The zero value is not considered valid. There is no maximal value.
- *
- * @param defaultValue The default value for the parameter, or {@link Double#NaN} if none.
- * @param unit The default unit, or {@code null} if none.
- * @return The parameter descriptor for the given default value and unit.
- */
- public ParameterDescriptor<Double> createStrictlyPositive(final double defaultValue, final Unit<?> unit) {
- final Range<Double> valueDomain;
- if (unit != null) {
- valueDomain = MeasurementRange.create(0.0, false, Double.POSITIVE_INFINITY, false, unit);
- } else {
- valueDomain = NumberRange.create(0.0, false, Double.POSITIVE_INFINITY, false);
- }
- return create(Double.class, valueDomain, null, Double.valueOf(defaultValue));
- }
-
- /**
- * Creates a descriptor for floating point values restricted to the given domain.
- *
- * @param minimumValue The minimum parameter value (inclusive), or {@link Double#NEGATIVE_INFINITY} if none.
- * @param maximumValue The maximum parameter value (inclusive), or {@link Double#POSITIVE_INFINITY} if none.
- * @param defaultValue The default value for the parameter, or {@link Double#NaN} if none.
- * @param unit The unit for default, minimum and maximum values, or {@code null} if none.
- * @return The parameter descriptor for the given domain of values.
- */
- public ParameterDescriptor<Double> createBounded(final double minimumValue, final double maximumValue,
- final double defaultValue, final Unit<?> unit)
- {
- final Range<Double> valueDomain;
- if (unit != null) {
- valueDomain = MeasurementRange.create(minimumValue, true, maximumValue, true, unit);
- } else if (minimumValue != Double.NEGATIVE_INFINITY || maximumValue != Double.POSITIVE_INFINITY) {
- valueDomain = NumberRange.create(minimumValue, true, maximumValue, true);
- } else {
- valueDomain = null;
- }
- return create(Double.class, valueDomain, null, Double.valueOf(defaultValue));
- }
-
- /**
- * Creates a descriptor for integer values restricted to the given domain.
- *
- * @param minimumValue The minimum parameter value (inclusive).
- * @param maximumValue The maximum parameter value (inclusive).
- * @param defaultValue The default value for the parameter.
- * @return The parameter descriptor for the given domain of values.
- */
- public ParameterDescriptor<Integer> createBounded(final int minimumValue, final int maximumValue,
- final int defaultValue)
- {
- return create(Integer.class, NumberRange.create(minimumValue, true, maximumValue, true), null, defaultValue);
- }
-
- /**
- * Creates a descriptor for values of the given type restricted to the given domain.
+ * {@preformat java
+ * public Foo createFoo() {
+ * onCreate(false);
+ * Foo foo = factory.createFoo(properties);
+ * onCreate(true);
+ * return foo;
+ * }
+ * }
*
- * @param <T> The compile-time type of the {@code valueClass} argument.
- * @param valueClass The class that describe the type of the parameter values.
- * @param minimumValue The minimum parameter value (inclusive), or {@code null} if none.
- * @param maximumValue The maximum parameter value (inclusive), or {@code null} if none.
- * @param defaultValue The default value for the parameter, or {@code null} if none.
- * @return The parameter descriptor for the given domain of values.
- */
- @SuppressWarnings({"unchecked", "rawtypes"})
- public <T extends Comparable<? super T>> ParameterDescriptor<T> createBounded(final Class<T> valueClass,
- final T minimumValue, final T maximumValue, final T defaultValue)
- {
- ensureNonNull("valueClass", valueClass);
- final Range<T> valueDomain;
- if (minimumValue == null && maximumValue == null) {
- valueDomain = null;
- } else if (Number.class.isAssignableFrom(valueClass)) {
- valueDomain = new NumberRange((Class) valueClass, (Number) minimumValue, true, (Number) maximumValue, true);
- } else {
- valueDomain = new Range<>(valueClass, minimumValue, true, maximumValue, true);
+ * If {@code cleanup} is {@code true}, then this method clears the identification information
+ * (name, aliases, identifiers and remarks) for preparing the builder to the construction of
+ * an other object. The authority, codespace and version properties are not cleared by this method.
+ *
+ * @param cleanup {@code false} when this method is invoked before object creation, and
+ * {@code true} when this method is invoked after object creation.
+ *
+ * @see #properties
+ */
+ protected void onCreate(final boolean cleanup) {
+ properties.put(IdentifiedObject.ALIAS_KEY, cleanup ? null : aliases .toArray(new GenericName [aliases .size()]));
+ properties.put(IdentifiedObject.IDENTIFIERS_KEY, cleanup ? null : identifiers.toArray(new ReferenceIdentifier[identifiers.size()]));
+ if (cleanup) {
+ properties .put(IdentifiedObject.NAME_KEY, null);
+ properties .remove(IdentifiedObject.REMARKS_KEY);
+ aliases .clear();
+ identifiers.clear();
}
- return create(valueClass, valueDomain, null, defaultValue);
- }
-
- /**
- * Creates a descriptor for a parameter restricted to a set of valid values.
- * The descriptor has no minimal or maximal value and no unit.
- *
- * <p>The {@code validValues} property is mostly for restricting values to
- * a {@linkplain org.opengis.util.CodeList code list} or enumeration subset.
- * It is not necessary to provide this property when all values from the code list or enumeration are valid.</p>
- *
- * @param <T> The compile-time type of the {@code valueClass} argument.
- * @param valueClass The class that describe the type of the parameter values.
- * @param validValues A finite set of valid values (usually from a {@linkplain CodeList code list})
- * or {@code null} if it doesn't apply.
- * @param defaultValue The default value for the parameter, or {@code null} if none.
- * @return The parameter descriptor for the given set of valid values.
- */
- public <T> ParameterDescriptor<T> createEnumerated(final Class<T> valueClass, final T[] validValues, final T defaultValue) {
- return create(valueClass, null, validValues, defaultValue);
- }
-
- /**
- * Invoked by all {@code createXXX(…)} method for creating the descriptor from the properties currently set
- * in this builder.
- */
- private <T> ParameterDescriptor<T> create(final Class<T> valueClass, final Range<?> valueDomain,
- final T[] validValues, final T defaultValue)
- {
- properties.put(ParameterDescriptor.ALIAS_KEY, aliases.toArray(new GenericName[aliases.size()]));
- properties.put(ParameterDescriptor.IDENTIFIERS_KEY, identifiers.toArray(new ReferenceIdentifier[identifiers.size()]));
- final ParameterDescriptor<T> descriptor = new DefaultParameterDescriptor<>(
- properties, valueClass, valueDomain, validValues, defaultValue, required);
- clearIdentification();
- return descriptor;
}
}
Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java?rev=1574562&r1=1574561&r2=1574562&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java [UTF-8] Wed Mar 5 16:23:53 2014
@@ -68,8 +68,8 @@ import java.util.Objects;
* <li><b>{@linkplain #head() Head}:</b> derived from the identifier {@linkplain #getCodeSpace() code space}.</li>
* <li><b>{@linkplain #scope() Scope}:</b> derived from the shortest {@linkplain #getAuthority() authority}'s
* {@linkplain Citation#getAlternateTitles() alternate titles}, or the {@linkplain Citation#getTitle() main title}
- * if there is no alternate titles. Note that according ISO 19115, citation alternate titles often contain
- * abbreviation (for example "DCW" as an alternative title for "<cite>Digital Chart of the World</cite>").</li>
+ * if there is no alternate titles. This policy exploits the ISO 19115 comment saying that citation alternate titles
+ * often contain abbreviation (for example "DCW" as an alternative title for "<cite>Digital Chart of the World</cite>").</li>
* </ul>
*
* <div class="note"><b>Example:</b>
Copied: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterBuilderTest.java (from r1574221, sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/DescriptorBuilderTest.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterBuilderTest.java?p2=sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterBuilderTest.java&p1=sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/DescriptorBuilderTest.java&r1=1574221&r2=1574562&rev=1574562&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/DescriptorBuilderTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/parameter/ParameterBuilderTest.java [UTF-8] Wed Mar 5 16:23:53 2014
@@ -30,7 +30,7 @@ import static org.junit.Assert.*;
/**
- * Tests {@link DescriptorBuilder}.
+ * Tests {@link ParameterBuilder}.
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.4
@@ -38,20 +38,20 @@ import static org.junit.Assert.*;
* @module
*/
@DependsOn({DefaultParameterDescriptorTest.class, DefaultParameterValueTest.class})
-public final strictfp class DescriptorBuilderTest extends TestCase {
+public final strictfp class ParameterBuilderTest extends TestCase {
/**
* Tests the "<cite>Mercator (variant A)</cite>" example given in Javadoc.
*/
@Test
- public void testMercatorExample() {
- final DescriptorBuilder builder = new DescriptorBuilder();
+ public void testMercatorProjection() {
+ final ParameterBuilder builder = new ParameterBuilder();
builder.codespace(HardCodedCitations.OGP, "EPSG").mandatory();
final ParameterDescriptor[] parameters = {
builder.name("Longitude of natural origin")
.name(HardCodedCitations.OGC, "central_meridian")
.name(HardCodedCitations.GEOTIFF, "NatOriginLong")
.remarks("Some remarks.") .createBounded(-180, +180, 0, NonSI.DEGREE_ANGLE),
- builder.name("Latitude of natural origin") .createBounded( -80, +80, 0, NonSI.DEGREE_ANGLE),
+ builder.name("Latitude of natural origin") .createBounded( -80, +84, 0, NonSI.DEGREE_ANGLE),
builder.name("Scale factor at natural origin") .createStrictlyPositive(1, Unit.ONE),
builder.name("False easting") .create(0, SI.METRE),
builder.name("False northing") .create(0, SI.METRE)
@@ -60,8 +60,9 @@ public final strictfp class DescriptorBu
assertEquals("EPSG", parameters[1].getName().getCodeSpace());
assertEquals("False easting", parameters[3].getName().getCode());
assertEquals("Some remarks.", parameters[0].getRemarks().toString());
- assertEquals(Double.valueOf(80), parameters[1].getMaximumValue());
+ assertEquals(Double.valueOf(84), parameters[1].getMaximumValue());
assertEquals(SI.METRE, parameters[4].getUnit());
+ assertTrue ( parameters[1].getAlias().isEmpty());
final GenericName alias = parameters[0].getAlias().iterator().next();
assertEquals("central_meridian", alias.tip().toString());
Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1574562&r1=1574561&r2=1574562&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Wed Mar 5 16:23:53 2014
@@ -53,7 +53,7 @@ import org.junit.BeforeClass;
org.apache.sis.parameter.DefaultParameterDescriptorTest.class,
org.apache.sis.parameter.DefaultParameterValueTest.class,
org.apache.sis.parameter.ParametersTest.class,
- org.apache.sis.parameter.DescriptorBuilderTest.class,
+ org.apache.sis.parameter.ParameterBuilderTest.class,
org.apache.sis.referencing.datum.BursaWolfParametersTest.class,
org.apache.sis.referencing.datum.TimeDependentBWPTest.class,
org.apache.sis.referencing.datum.DefaultEllipsoidTest.class,