Package org.apache.sis.parameter

Source Code of org.apache.sis.parameter.ParameterBuilder

/*
* 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.parameter;

import javax.measure.unit.Unit;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.GeneralParameterDescriptor;
import org.apache.sis.measure.MeasurementRange;
import org.apache.sis.measure.NumberRange;
import org.apache.sis.measure.Range;
import org.apache.sis.referencing.Builder;

import static org.apache.sis.util.ArgumentChecks.ensureNonNull;


/**
* Helper class for {@linkplain DefaultParameterDescriptor parameter descriptor} instantiations.
* This builder can be helpful to operation or process <em>providers</em> (e.g. map projection
* implementors). Operation <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 addName(…)} methods.
* Parameters can optionally have an arbitrary amount of aliases, which are also specified by the
* {@code addName(…)} 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 addIdentifier(…)} 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 setRemarks(…)} method.</p>
*
* <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>
*
* {@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. The projection is valid from 80°S to 84°N and on all the
* longitude range (±180°).
*
* {@preformat java
*   ParameterBuilder builder = new ParameterBuilder();
*   builder.setCodeSpace(Citations.OGP, "EPSG").setRequired(true);
*   ParameterDescriptor<?>[] parameters = {
*       builder.addName("Latitude of natural origin")    .createBounded( -80,  +84, 0, NonSI.DEGREE_ANGLE),
*       builder.addName("Longitude of natural origin")   .createBounded(-180, +180, 0, NonSI.DEGREE_ANGLE),
*       builder.addName("Scale factor at natural origin").createStrictlyPositive(1, Unit.ONE),
*       builder.addName("False easting")                 .create(0, SI.METRE),
*       builder.addName("False northing")                .create(0, SI.METRE)
*   };
* }
*
* Parameters often have more than one name, because different softwares or standards use different conventions.
* In the above example, the line creating the <cite>Longitude of natural origin</cite> parameter could be replaced
* by the following code in order to declare its aliases:
*
* {@preformat java
*   builder.addIdentifier("8802")                         // Primary key in builder default namespace (EPSG in this example).
*          .addName("Longitude of natural origin")        // Primary name in builder default namespace (EPSG in this example).
*          .addName(Citations.OGC, "central_meridian")    // First alias in "OGC" namespace.
*          .addName(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 ParameterBuilder extends Builder<ParameterBuilder> {
    /**
     * {@code true} if the parameter is mandatory, or {@code false} if optional.
     *
     * @see #setRequired(boolean)
     */
    private boolean required;

    /**
     * Creates a new builder.
     */
    public ParameterBuilder() {
    }

    /**
     * Sets whether the parameter is mandatory or optional.
     * This property determines the {@linkplain DefaultParameterDescriptor#getMinimumOccurs() minimum number
     * of times} that values are required, which will be 0 for an optional parameter and 1 for a mandatory one.
     *
     * <p><b>Default value:</b>
     * If this method is never invoked, then the default value is {@code false}.</p>
     *
     * <p><b>Lifetime:</b>
     * this property is kept unchanged until this {@code setRequired(…)} method is invoked again.</p>
     *
     * @param  required {@code true} for a mandatory parameter, or {@code false} for an optional one.
     * @return {@code this}, for method call chaining.
     */
    public ParameterBuilder setRequired(final boolean required) {
        this.required = required;
        return this;
    }

    /**
     * Creates a descriptor for floating point values without domain restriction.
     * All {@code double} values are considered valid.
     *
     * @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 values of the given type without domain restriction.
     *
     * @param  <T>          The compile-time type of the {@code valueClass} argument.
     * @param  valueClass   The class that describe the type of the parameter values.
     * @param  defaultValue The default value for the parameter, or {@code null} if none.
     * @return The parameter descriptor for the given default value and unit.
     */
    public <T> ParameterDescriptor<T> create(final Class<T> valueClass, final T defaultValue) {
        return create(valueClass, null, null, 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.
     *
     * @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<T>(valueClass, minimumValue, true, maximumValue, true);
        }
        return create(valueClass, valueDomain, null, defaultValue);
    }

    /**
     * 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.
     *
     * <p>The {@code validValues} property is mostly for restricting values to
     * a {@linkplain org.opengis.util.CodeList code list} or {@linkplain Enum 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 code list or enumeration)
     *                      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) {
        ensureNonNull("valueClass", valueClass);
        return create(valueClass, null, validValues, defaultValue);
    }

    /**
     * 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)
    {
        final ParameterDescriptor<T> descriptor;
        onCreate(false);
        try {
            descriptor = new DefaultParameterDescriptor<T>(properties,
                    valueClass, valueDomain, validValues, defaultValue, required);
        } finally {
            onCreate(true);
        }
        return descriptor;
    }

    /**
     * Creates a descriptor group for the given parameters. This is a convenience method for
     * {@link #createGroup(int, int, GeneralParameterDescriptor[])} with a cardinality of [0 … 1]
     * or [1 … 1] depending on the value given to the last call to {@link #setRequired(boolean)}.
     *
     * @param  parameters The {@linkplain DefaultParameterDescriptorGroup#descriptors() parameter descriptors}
     *         for the group to create.
     * @return The parameter descriptor group.
     */
    public ParameterDescriptorGroup createGroup(final GeneralParameterDescriptor... parameters) {
        return createGroup(required ? 1 : 0, 1, parameters);
    }

    /**
     * Creates a descriptor group for the given cardinality and parameters.
     *
     * @param  minimumOccurs The {@linkplain DefaultParameterDescriptorGroup#getMinimumOccurs() minimum}
     *                       number of times that values for this parameter group are required.
     * @param  maximumOccurs The {@linkplain DefaultParameterDescriptorGroup#getMaximumOccurs() maximum}
     *                       number of times that values for this parameter group are required.
     * @param  parameters    The {@linkplain DefaultParameterDescriptorGroup#descriptors() parameter descriptors}
     *                       for the group to create.
     * @return The parameter descriptor group.
     */
    public ParameterDescriptorGroup createGroup(final int minimumOccurs, final int maximumOccurs,
            final GeneralParameterDescriptor... parameters)
    {
        final ParameterDescriptorGroup group;
        onCreate(false);
        try {
            group = new DefaultParameterDescriptorGroup(properties, minimumOccurs, maximumOccurs, parameters);
        } finally {
            onCreate(true);
        }
        return group;
    }
}
TOP

Related Classes of org.apache.sis.parameter.ParameterBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.