/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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.
*/
package org.geotools.parameter;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogRecord;
import javax.measure.unit.Unit;
import org.opengis.parameter.GeneralParameterDescriptor;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.ParameterValue;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.parameter.ParameterNotFoundException;
import org.opengis.parameter.InvalidParameterTypeException;
import org.geotools.referencing.AbstractIdentifiedObject;
import org.geotools.util.logging.Logging;
import org.geotools.resources.Classes;
import org.geotools.resources.i18n.Errors;
import org.geotools.resources.i18n.ErrorKeys;
/**
* Utility class for methods helping implementing, and working with the
* parameter API from {@link org.opengis.parameter} package.
*
*
Design note
* This class contains some methods working on a specific parameter in a group (e.g.
* {@linkplain #search searching}, {@linkplain #ensureSet setting a value}, etc.).
* Parameters are identified by their {@linkplain ParameterDescriptor#getName name} instead of
* their full {@linkplain ParameterDescriptor descriptor} object, because:
*
*
The parameter descriptor may not be always available. For example a user may looks for
* the {@code "semi_major"} axis length (because it is documented in OGC specification under
* that name) but doesn't know and doesn't care about who is providing the implementation. In
* such case, he doesn't have the parameter's descriptor. He only have the parameter's name,
* and creating a descriptor from that name (a descriptor independent of any implementation)
* is tedious.
.
*
Parameter descriptors are implementation-dependent. For example if a user searchs for
* the above-cited {@code "semi_major"} axis length using the {@linkplain
* org.geotools.referencing.operation.projection.MapProjection.AbstractProvider#SEMI_MAJOR
* Geotools's descriptor} for this parameter, we will fail to find this parameter in any
* alternative {@link ParameterValueGroup} implementations. This is against GeoAPI's
* inter-operability goal.
*
*
* The above doesn't mean that parameter's descriptor should not be used. They are used for
* inspecting meta-data about parameters, not as a key for searching parameters in a group.
* Since each parameter's name should be unique in a given parameter group (because
* {@linkplain ParameterDescriptor#getMaximumOccurs maximum occurs} is always 1 for single
* parameter), the parameter name is a suffisient key.
*
* @since 2.1
*
*
* @source $URL$
* @version $Id$
* @author Jody Garnett (Refractions Research)
* @author Martin Desruisseaux
*/
public final class Parameters {
/**
* Small number for floating point comparaisons.
*/
private static final double EPS = 1E-8;
/**
* An empty parameter group. This group contains no parameters.
*/
public static ParameterDescriptorGroup EMPTY_GROUP =
new DefaultParameterDescriptorGroup("empty", // TODO: localize
new GeneralParameterDescriptor[0]);
/**
* Do not allows instantiation of this utility class.
*/
private Parameters() {
}
/**
* Casts the given parameter descriptor to the given type. An exception is thrown
* immediately if the parameter does not have the expected value class. This
* is a helper method for type safety when using Java 5 parameterized types.
*
* @param The expected value class.
* @param descriptor The descriptor to cast.
* @param type The expected value class.
* @return The descriptor casted to the given type.
* @throws ClassCastException if the given descriptor doesn't have the expected value class.
*
* @since 2.5
*/
@SuppressWarnings("unchecked")
public static ParameterDescriptor cast(ParameterDescriptor> descriptor, Class type)
throws ClassCastException
{
if (descriptor != null) {
final Class> actual = descriptor.getValueClass();
// We require a strict equality - not type.isAssignableFrom(actual) - because in
// the later case we could have (to be strict) to return a extends T> type.
if (!type.equals(actual)) {
throw new ClassCastException(Errors.format(ErrorKeys.BAD_PARAMETER_TYPE_$2,
descriptor.getName().getCode(), actual));
}
}
return (ParameterDescriptor) descriptor;
}
/**
* Casts the given parameter value to the given type. An exception is thrown
* immediately if the parameter does not have the expected value class. This
* is a helper method for type safety when using Java 5 parameterized types.
*
* @param The expected value class.
* @param value The value to cast.
* @param type The expected value class.
* @return The value casted to the given type.
* @throws ClassCastException if the given value doesn't have the expected value class.
*
* @since 2.5
*/
@SuppressWarnings("unchecked")
public static ParameterValue cast(final ParameterValue> value, final Class type)
throws ClassCastException
{
if (value != null) {
final ParameterDescriptor descriptor = value.getDescriptor();
final Class> actual = descriptor.getValueClass();
if (!type.equals(actual)) { // Same comment than cast(ParameterDescriptor)...
throw new ClassCastException(Errors.format(ErrorKeys.BAD_PARAMETER_TYPE_$2,
descriptor.getName().getCode(), actual));
}
}
return (ParameterValue) value;
}
/**
* Checks a parameter value against its {@linkplain ParameterDescriptor parameter descriptor}.
* This method takes care of handling checking arrays and collections against parameter
* descriptor.
*
* When the {@linkplain ParameterDescriptor#getValueClass value class} is an array (like
* {@code double[].class}) or a {@linkplain Collection collection} (like {@code List.class}),
* the descriptor
* {@linkplain ParameterDescriptor#getMinimumValue minimum value},
* {@linkplain ParameterDescriptor#getMaximumValue maximum value} and
* {@linkplain ParameterDescriptor#getValidValues valid values}
* will be used to check the elements.
*
* @param parameter The parameter to test.
* @return true if parameter is valid.
*
* @see Parameter#ensureValidValue
*/
public static boolean isValid(final ParameterValue> parameter) {
final ParameterDescriptor> descriptor = parameter.getDescriptor();
final Object value = parameter.getValue();
if (value == null) {
// Accepts null values only if explicitly authorized.
final Set> validValues = descriptor.getValidValues();
return validValues != null && validValues.contains(value);
}
final Class> type = Classes.primitiveToWrapper(value.getClass());
final Class> expected = Classes.primitiveToWrapper(descriptor.getValueClass());
if (expected.isAssignableFrom(type)) {
return false; // value not of the correct type
}
if (type.isArray()) {
// handle checking elements in an aray
final int length = Array.getLength(value);
for (int i=0; i descriptor) {
final Set> validValues = descriptor.getValidValues();
if (validValues != null && !validValues.contains(value)) {
return false;
}
@SuppressWarnings("unchecked") // Type has been verified by the caller.
final Comparable