All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geotoolkit.parameter.ParameterGroup Maven / Gradle / Ivy

Go to download

Implementations of Coordinate Reference Systems (CRS), conversion and transformation services derived from ISO 19111.

There is a newer version: 3.20-geoapi-3.0
Show newest version
/*
 *    Geotoolkit.org - An Open Source Java GIS Toolkit
 *    http://www.geotoolkit.org
 *
 *    (C) 2004-2011, Open Source Geospatial Foundation (OSGeo)
 *    (C) 2009-2011, Geomatys
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    This package contains documentation from OpenGIS specifications.
 *    OpenGIS consortium's work is fully acknowledged here.
 */
package org.geotoolkit.parameter;

import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;

import org.opengis.metadata.Identifier;
import org.opengis.parameter.ParameterValue;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.GeneralParameterDescriptor;
import org.opengis.parameter.ParameterNotFoundException;
import org.opengis.parameter.InvalidParameterTypeException;
import org.opengis.parameter.InvalidParameterCardinalityException;

import org.geotoolkit.util.Utilities;
import org.geotoolkit.resources.Errors;
import org.geotoolkit.util.collection.XCollections;
import org.geotoolkit.referencing.IdentifiedObjects;

import static org.geotoolkit.util.ArgumentChecks.ensureNonNull;


/**
 * A group of related parameter values. The same group can be repeated more than once in
 * an {@linkplain org.opengis.referencing.operation.Operation operation} or higher level
 * {@link ParameterValueGroup}, if those instances contain different values of one or more
 * {@link ParameterValue}s which suitably distinguish among those groups.
 *
 * @author Martin Desruisseaux (IRD)
 * @author Jody Garnett (Refractions)
 * @version 3.17
 *
 * @see DefaultParameterDescriptorGroup
 * @see Parameter
 *
 * @since 2.0
 * @module
 */
public class ParameterGroup extends AbstractParameter implements ParameterValueGroup {
    /**
     * Serial number for inter-operability with different versions.
     */
    private static final long serialVersionUID = -1985309386356545126L;

    /**
     * An empty parameter value group. This group contains no parameter value.
     */
    public static final ParameterValueGroup EMPTY = new ParameterGroup(
            Collections.singletonMap(ParameterDescriptorGroup.NAME_KEY, "Void"));

    /**
     * The {@linkplain #values() parameter values} for this group.
     *
     * {@note Consider this field as final. This field is not final
     *        only in order to allow the clone method to work.}
     */
    private ArrayList values;

    /**
     * A view of {@link #values} as an immutable list. Will be constructed only when first
     * needed. Note that while this list may be immutable, elements in this
     * list stay modifiable. The goal is to allows the following idiom:
     *
     * {@preformat java
     *     values().get(i).setValue(myValue);
     * }
     */
    private transient List asList;

    /**
     * Constructs a parameter group from the specified descriptor.
     * All {@linkplain #values parameter values} will be initialized
     * to their default value.
     *
     * @param descriptor The descriptor for this group.
     */
    public ParameterGroup(final ParameterDescriptorGroup descriptor) {
        super(descriptor);
        final List parameters = descriptor.descriptors();
        values = new ArrayList(parameters.size());
        for (final GeneralParameterDescriptor element : parameters) {
            for (int count=element.getMinimumOccurs(); --count>=0;) {
                final GeneralParameterValue value = element.createValue();
                ensureNonNull("createValue", value);
                values.add(value);
            }
        }
    }

    /**
     * Constructs a parameter group from the specified descriptor and list of parameters.
     *
     * @param  descriptor The descriptor for this group.
     * @param  values The list of parameter values.
     * @throws IllegalStateException If the number of parameter values is not in the
     *         range of minimum and maximum occurrences declared in the descriptor.
     */
    public ParameterGroup(final ParameterDescriptorGroup descriptor,
                          final GeneralParameterValue... values)
    {
        super(descriptor);
        ensureNonNull("values", values);
        this.values = new ArrayList(Arrays.asList(values));
        final List parameters = descriptor.descriptors();
        final Map occurrences =
                new LinkedHashMap(XCollections.hashMapCapacity(parameters.size()));
        for (final GeneralParameterDescriptor param : parameters) {
            ensureNonNull("parameters", param);
            occurrences.put(param, new int[1]);
            // The value 'int[1]' will be used by 'ensureValidOccurs'
        }
        ensureValidOccurs(values, occurrences);
    }

    /**
     * Constructs a parameter group from the specified list of parameters.
     *
     * @param  properties The properties for the {@linkplain DefaultParameterDescriptorGroup
     *         operation parameter group} to construct from the list of parameters.
     * @param  values The list of parameter values.
     * @throws IllegalStateException If the number of parameter values is not in the
     *         range of minimum and maximum occurrences declared in the descriptor.
     */
    public ParameterGroup(final Map properties, final GeneralParameterValue... values) {
        super(createDescriptor(properties, values));
        this.values = new ArrayList(Arrays.asList(values));
    }

    /**
     * Work around for RFE #4093999 in Sun's bug database
     * ("Relax constraint on placement of this()/super() call in constructors").
     *
     * @throws IllegalStateException If the number of parameter values is not in the
     *         range of minimum and maximum occurrences declared in the descriptor.
     */
    private static ParameterDescriptorGroup createDescriptor(
            final Map properties, final GeneralParameterValue[] values)
    {
        ensureNonNull("values", values);
        final Map occurrences =
                new LinkedHashMap(XCollections.hashMapCapacity(values.length));
        for (int i=0; i descriptors = occurrences.keySet();
        return new DefaultParameterDescriptorGroup(properties,
                descriptors.toArray(new GeneralParameterDescriptor[descriptors.size()]));
    }

    /**
     * Makes sure that the number of occurrences of each values is inside the expected range.
     *
     * @param  values The list of parameter values.
     * @param  occurrences A map of the number of occurrences of a value for each descriptor.
     *         The key must be {@link GeneralParameterDescriptor} instances and the values
     *         must be {@code int[]} array of length 1 initialized with the 0 value.
     * @throws IllegalStateException If the number of parameter values is not in the
     *         range of minimum and maximum occurrences declared in the descriptor.
     */
    private static void ensureValidOccurs(final GeneralParameterValue[] values,
                                          final Map occurrences)
    {
        /*
         * Count the parameters occurrences.
         */
        for (int i=0; i entry : occurrences.entrySet()) {
            final GeneralParameterDescriptor descriptor = entry.getKey();
            final int count = entry.getValue()[0];
            final int min   = descriptor.getMinimumOccurs();
            final int max   = descriptor.getMaximumOccurs();
            if (!(count>=min && count<=max)) {
                final String name = getName(descriptor);
                throw new InvalidParameterCardinalityException(Errors.format(
                        Errors.Keys.ILLEGAL_OCCURS_FOR_PARAMETER_$4, name, count, min, max), name);
            }
        }
    }

    /**
     * Returns the abstract definition of this group of parameters.
     */
    @Override
    public ParameterDescriptorGroup getDescriptor() {
        return (ParameterDescriptorGroup) super.getDescriptor();
    }

    /**
     * Returns the values in this group. Changes in this list are reflected on this
     * {@code ParameterValueGroup}. The returned list supports the
     * {@link List#add(Object) add} operation.
     */
    @Override
    public List values() {
        if (asList == null) {
            asList = new ParameterValueList((ParameterDescriptorGroup) descriptor, values);
        }
        return asList;
    }

    /**
     * Returns the parameter value at the specified index.
     *
     * @param  index The zero-based index.
     * @return The parameter value at the specified index.
     * @throws IndexOutOfBoundsException if the specified index is out of bounds.
     */
    final GeneralParameterValue parameter(final int index) throws IndexOutOfBoundsException {
        return values.get(index);
    }

    /**
     * Returns the value in this group for the specified {@linkplain Identifier#getCode identifier code}.
     * If no {@linkplain ParameterValue parameter value} is found but a {@linkplain ParameterDescriptor
     * parameter descriptor} is found (which may occurs if the parameter is optional, i.e.
     * {@linkplain ParameterDescriptor#getMinimumOccurs minimumOccurs} == 0),
     * then a {@linkplain ParameterValue parameter value} is automatically created and initialized
     * to its {@linkplain ParameterDescriptor#getDefaultValue default value} (if any).
     * 

* This convenience method provides a way to get and set parameter values by name. For example * the following idiom fetches a floating point value for the {@code "false_easting"} parameter: * * {@preformat java * double value = parameter("false_easting").doubleValue(); * } * * This method does not search recursively in subgroups. This is because more than one subgroup * may exist for the same {@linkplain ParameterDescriptorGroup descriptor}. The user must * {@linkplain #groups query all subgroups} and select explicitly the appropriate one to use. * * @param name The case insensitive {@linkplain Identifier#getCode identifier code} of the * parameter to search for. * @return The parameter value for the given identifier code. * @throws ParameterNotFoundException if there is no parameter value for the given identifier * code. * * @see Parameters#getOrCreate(ParameterDescriptor, ParameterValueGroup) */ @Override public ParameterValue parameter(String name) throws ParameterNotFoundException { ensureNonNull("name", name); name = name.trim(); for (final GeneralParameterValue value : values) { if (value instanceof ParameterValue) { if (IdentifiedObjects.nameMatches(value.getDescriptor(), name)) { return (ParameterValue) value; } } } /* * No existing parameter found. Check if an optional parameter exists. * If such a descriptor is found, create it, add it to the list of values * and returns it. */ for (final GeneralParameterDescriptor descriptor : getDescriptor().descriptors()) { if (descriptor instanceof ParameterDescriptor) { if (IdentifiedObjects.nameMatches(descriptor, name)) { final ParameterValue value = ((ParameterDescriptor) descriptor).createValue(); values.add(value); return value; } } } throw new ParameterNotFoundException(Errors.format(Errors.Keys.UNKNOWN_PARAMETER_NAME_$1, name), name); } /** * Returns all subgroups with the specified name. This method do not create new groups. * If the requested group is optional (i.e. * {@linkplain ParameterDescriptor#getMinimumOccurs minimumOccurs} == 0) * and no value were set, then this method returns an empty set. * * @param name The case insensitive {@linkplain Identifier#getCode identifier code} * of the parameter group to search for. * @return The set of all parameter group for the given identifier code. * @throws ParameterNotFoundException If no {@linkplain ParameterDescriptorGroup descriptor} * was found for the given name. */ @Override public List groups(String name) throws ParameterNotFoundException { ensureNonNull("name", name); name = name.trim(); final List groups = new ArrayList(Math.min(values.size(), 10)); for (final GeneralParameterValue value : values) { if (value instanceof ParameterValueGroup) { if (IdentifiedObjects.nameMatches(value.getDescriptor(), name)) { groups.add((ParameterValueGroup) value); } } } /* * No groups were found. Check if the group actually exists (i.e. is declared in the * descriptor). If it doesn't exists, then an exception is thrown. If it exists (i.e. * it is simply an optional group not yet defined), then returns an empty list. */ if (groups.isEmpty()) { final GeneralParameterDescriptor check = ((ParameterDescriptorGroup) descriptor).descriptor(name); if (!(check instanceof ParameterDescriptorGroup)) { throw new ParameterNotFoundException(Errors.format( Errors.Keys.UNKNOWN_PARAMETER_NAME_$1, name), name); } } return groups; } /** * Creates a new group of the specified name. The specified name must be the * {@linkplain Identifier#getCode identifier code} of a {@linkplain ParameterDescriptorGroup * descriptor group}. * * @param name The case insensitive {@linkplain Identifier#getCode identifier code} of the * parameter group to create. * @return A newly created parameter group for the given identifier code. * @throws ParameterNotFoundException If no {@linkplain ParameterDescriptorGroup descriptor} * was found for the given name. * @throws InvalidParameterCardinalityException If this parameter group already contains the * {@linkplain ParameterDescriptorGroup#getMaximumOccurs maximum number of occurrences} * of subgroups of the given name. */ @Override public ParameterValueGroup addGroup(String name) throws ParameterNotFoundException, InvalidParameterCardinalityException { final GeneralParameterDescriptor check = ((ParameterDescriptorGroup) descriptor).descriptor(name); if (!(check instanceof ParameterDescriptorGroup)) { throw new ParameterNotFoundException(Errors.format( Errors.Keys.UNKNOWN_PARAMETER_NAME_$1, name), name); } int count = 0; for (final GeneralParameterValue value : values) { if (IdentifiedObjects.nameMatches(value.getDescriptor(), name)) { count++; } } if (count >= check.getMaximumOccurs()) { throw new InvalidParameterCardinalityException(Errors.format( Errors.Keys.TOO_MANY_OCCURRENCES_$2, name, count), name); } final ParameterValueGroup value = ((ParameterDescriptorGroup) check).createValue(); values.add(value); return value; } /** * Compares the specified object with this parameter for equality. * * @param object The object to compare to {@code this}. * @return {@code true} if both objects are equal. */ @Override public boolean equals(final Object object) { if (object == this) { return true; } if (super.equals(object)) { final ParameterGroup that = (ParameterGroup) object; return Utilities.equals(this.values, that.values); } return false; } /** * Returns a hash value for this parameter. * * @return The hash code value. This value doesn't need to be the same * in past or future versions of this class. */ @Override public int hashCode() { return super.hashCode() ^ values.hashCode(); } /** * Returns a deep copy of this group of parameter values. * Included parameter values and subgroups are cloned recursively. * * @return A copy of this group of parameter values. */ @Override @SuppressWarnings("unchecked") public ParameterGroup clone() { final ParameterGroup copy = (ParameterGroup) super.clone(); copy.values = (ArrayList) copy.values.clone(); for (int i=copy.values.size(); --i>=0;) { copy.values.set(i, copy.values.get(i).clone()); } copy.asList = null; return copy; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy