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

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

/*
 *    Geotoolkit.org - An Open Source Java GIS Toolkit
 *    http://www.geotoolkit.org
 *
 *    (C) 2004-2012, Open Source Geospatial Foundation (OSGeo)
 *    (C) 2009-2012, 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.
 */
package org.geotoolkit.parameter;

import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import javax.measure.unit.Unit;

import org.opengis.util.InternationalString;
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.metadata.quality.ConformanceResult;
import org.opengis.metadata.Identifier;

import org.geotoolkit.lang.Static;
import org.geotoolkit.resources.Errors;
import org.geotoolkit.resources.Vocabulary;
import org.geotoolkit.resources.Descriptions;
import org.geotoolkit.util.logging.Logging;
import org.geotoolkit.referencing.IdentifiedObjects;
import org.geotoolkit.metadata.iso.quality.DefaultConformanceResult;
import org.geotoolkit.naming.DefaultNameSpace;


/**
 * Helper methods for working with the parameter API from {@link org.opengis.parameter} package.
 * This class provides methods for {@linkplain #search searching}, {@linkplain #ensureSet setting
 * a value}, etc. from a parameter name.
 * Names in simple {@code String} form are preferred over the full {@code ParameterDescriptor}
 * 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 searches for * the above-cited {@code "semi_major"} axis length using the {@linkplain * org.geotoolkit.referencing.operation.provider.MapProjection#SEMI_MAJOR Geotk's descriptor} * for that parameter, we will fail to find this parameter in any alternative * {@link ParameterValueGroup} implementations. This is against GeoAPI's inter-operability goal.

  • *
* * When a method in this class expects a full {@code ParameterDescriptor} object in argument * (for example {@link #value(ParameterDescriptor, ParameterValueGroup)}), the * {@linkplain ParameterDescriptor#getName descriptor name} and alias are used for the search - this * class does not look for strictly equal {@code ParameterDescriptor} objects. * * @author Jody Garnett (Refractions) * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.20 * * @since 2.1 * @module */ public final class Parameters extends Static { /** * Small number for floating point comparisons. */ private static final double EPS = 1E-8; /** * The explanation for conformance results. */ private static final InternationalString EXPLAIN = Descriptions.formatInternational(Descriptions.Keys.CONFORMANCE_MEANS_VALID_PARAMETERS); /** * An empty parameter group. This group contains no parameters. */ public static final ParameterDescriptorGroup EMPTY_GROUP = new DefaultParameterDescriptorGroup(Vocabulary.format(Vocabulary.Keys.EMPTY)); /** * 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, or {@code null}. * @param type The expected value class. * @return The descriptor casted to the given type, or {@code null} if the given descriptor was null. * @throws ClassCastException if the given descriptor doesn't have the expected value class. * * @category verification * @since 2.5 */ @SuppressWarnings("unchecked") public static ParameterDescriptor cast(final ParameterDescriptor descriptor, final 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 type. if (!type.equals(actual)) { throw new ClassCastException(Errors.format(Errors.Keys.ILLEGAL_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, or {@code null}. * @param type The expected value class. * @return The value casted to the given type, or {@code null} if the given value was null. * @throws ClassCastException if the given value doesn't have the expected value class. * * @category verification * @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(Errors.Keys.ILLEGAL_PARAMETER_TYPE_$2, descriptor.getName().getCode(), actual)); } } return (ParameterValue) value; } /** * Checks a parameter value against its {@linkplain ParameterDescriptor parameter descriptor}. * This method compares the {@linkplain ParameterValue#getValue() value} against the expected * {@linkplain ParameterDescriptor#getValueClass value class}, the * [{@linkplain ParameterDescriptor#getMinimumValue minimum} … * {@linkplain ParameterDescriptor#getMaximumValue maximum}] range and the set of * {@linkplain ParameterDescriptor#getValidValues valid values}. *

* This is a convenience method for testing a single parameter value assuming that its * descriptor is correct. It returns a {@code boolean} because in case of failure, the * faulty parameter is known: it is the one given in argument to this method. For a more * generic test which can work on group of parameters and provide more details about which * parameter failed and why, use the * {@link #isValid(GeneralParameterValue, GeneralParameterDescriptor)} method instead. * * @param value The parameter to test. * @return {@code true} if the given parameter is valid. * * @category verification */ public static boolean isValid(final ParameterValue value) { return isValidValue(value.getDescriptor(), value.getValue(), false) == null; } /** * Checks a parameter value against its descriptor, and returns an error message if it is * not conformant. This method is similar to {@link AbstractParameter#ensureValidValue}. * If one implementation is modified, the other one should be updated accordingly. * * @param The expected type of value. * @param parameter The parameter to test. * @param localized {@code true} if a fully localized message is wanted in case of failure, * or {@code false} for a sentinel value (not useful for reporting to the user). * @param descriptor The descriptor to use for fetching the conditions. * @return {@code null} if the given parameter is valid, or an error message otherwise. */ private static InternationalString isValidValue(final ParameterDescriptor descriptor, final Object value, final boolean localized) { /* * Accept null values only if explicitly authorized. */ if (value == null) { if (descriptor.getMinimumOccurs() == 0) { return null; // Test pass. } return localized ? Errors.formatInternational(Errors.Keys.NO_PARAMETER_$1, AbstractParameter.getName(descriptor)) : EXPLAIN; } /* * Check the type. */ final Class type = value.getClass(); final Class expected = descriptor.getValueClass(); if (!expected.isAssignableFrom(type)) { return localized ? Errors.formatInternational(Errors.Keys.ILLEGAL_CLASS_$2, type, expected) : EXPLAIN; } final T typedValue = expected.cast(value); /* * Check the range (if any). */ final Comparable minimum = descriptor.getMinimumValue(); final Comparable maximum = descriptor.getMaximumValue(); if ((minimum != null && minimum.compareTo(typedValue) > 0) || (maximum != null && maximum.compareTo(typedValue) < 0)) { return localized ? Errors.formatInternational(Errors.Keys.VALUE_OUT_OF_BOUNDS_$3, value, minimum, maximum) : EXPLAIN; } /* * Check the enumeration (if any). */ final Set validValues = descriptor.getValidValues(); if (validValues!=null && !validValues.contains(value)) { return localized ? Errors.formatInternational(Errors.Keys.ILLEGAL_ARGUMENT_$2, AbstractParameter.getName(descriptor), value) : EXPLAIN; } return null; // Test pass. } /** * Checks a parameter value against the conditions specified by the given descriptor. * If the given parameter is an instance of {@link ParameterValue}, then this method * compares the {@linkplain ParameterValue#getValue() value} against the expected * {@linkplain ParameterDescriptor#getValueClass value class}, the * [{@linkplain ParameterDescriptor#getMinimumValue minimum} … * {@linkplain ParameterDescriptor#getMaximumValue maximum}] range and the set of * {@linkplain ParameterDescriptor#getValidValues valid values}. * If this method is an instance of {@link ParameterValueGroup}, then the check * is applied recursively for every parameter in this group. * * @param value The parameter to test. * @param descriptor The descriptor to use for fetching the conditions. * @return A conformance result having the attribute {@linkplain ConformanceResult#pass() * pass}=true if the parameter is valid. If the parameter is not valid, then * the result {@linkplain ConformanceResult#getExplanation() explanation} gives the * raison. * * @since 3.05 * @category verification */ public static ConformanceResult isValid(final GeneralParameterValue value, final GeneralParameterDescriptor descriptor) { /* * Create a conformance result initialized to a successful check. */ final DefaultConformanceResult result = new DefaultConformanceResult( descriptor.getName().getAuthority(), EXPLAIN, true); final GeneralParameterValue failure = isValid(value, descriptor, result); /* * If the validity test failed, update the conformance result accordingly. */ if (failure != null) { final Identifier name = failure.getDescriptor().getName(); result.setExplanation(Descriptions.formatInternational( Descriptions.Keys.NON_CONFORM_PARAMETER_$2, name, result.getExplanation())); result.setSpecification(name.getAuthority()); result.setPass(Boolean.FALSE); } return result; } /** * Checks a parameter value against the conditions specified by the given descriptor. * In case of failure, the explanation message of the given {@code result} is updated * with the cause, and this method returns the descriptor of the parameter that failed * the check. * * @param value The parameter to test. * @param descriptor The descriptor to use for fetching the conditions. * @param result The conformance result to update in case of failure. * @return {@code null} in case of success, or the faulty parameter in case of failure. */ private static GeneralParameterValue isValid(final GeneralParameterValue value, final GeneralParameterDescriptor descriptor, final DefaultConformanceResult result) { if (descriptor instanceof ParameterDescriptor) { /* * For a single parameter (the most common case), the value shall be an instance * of ParameterValue. If it is not, then the error message will be formatted at * the end of this method. */ if (value instanceof ParameterValue) { final InternationalString failure = isValidValue((ParameterDescriptor) descriptor, ((ParameterValue) value).getValue(), true); if (failure != null) { result.setExplanation(failure); return value; } return null; // The test pass. } } else if (descriptor instanceof ParameterDescriptorGroup) { /* * For a group, the value shall be an instance of ParameterValueGroup. If it * is not, then the error message will be formatted at the end of this method. */ if (value instanceof ParameterValueGroup) { final Map count = new HashMap(); final ParameterDescriptorGroup group = (ParameterDescriptorGroup) descriptor; for (final GeneralParameterValue element : ((ParameterValueGroup) value).values()) { final String name = getName(element.getDescriptor(), group); final GeneralParameterDescriptor desc; try { desc = group.descriptor(name); } catch (ParameterNotFoundException e) { result.setExplanation(Errors.formatInternational( Errors.Keys.UNEXPECTED_PARAMETER_$1, name)); return value; } final GeneralParameterValue failure = isValid(element, desc, result); if (failure != null) { return failure; } // Count the occurrence of parameters. Integer old = count.put(desc, 1); if (old != null) { count.put(desc, old + 1); } } /* * All parameters pass their individual test. * Now check their cardinality. */ for (final GeneralParameterDescriptor desc : group.descriptors()) { final Integer nw = count.get(desc); final int n = (nw != null) ? nw : 0; final int min = desc.getMinimumOccurs(); final int max = desc.getMaximumOccurs(); if (n < min || n > max) { final String name = desc.getName().getCode(); final int key; final Object[] param; if (n == 0) { key = Errors.Keys.NO_PARAMETER_$1; param = new Object[] {name}; } else { key = Errors.Keys.ILLEGAL_OCCURS_FOR_PARAMETER_$4; param = new Object[] {name, nw, min, max}; } result.setExplanation(Errors.formatInternational(key, param)); return value; } } return null; // The test pass. } } /* * If we reach this point, the type of the parameter value is not consistent * with the type of the descriptor. Format the error message. */ final Class type; if (value instanceof ParameterValue) { type = ParameterValue.class; } else if (value instanceof ParameterValueGroup) { type = ParameterValueGroup.class; } else { type = GeneralParameterValue.class; } result.setExplanation(Errors.formatInternational(Errors.Keys.ILLEGAL_OPERATION_FOR_VALUE_CLASS_$1, type)); return value; } /** * Returns the name of the given parameter, using the authority code space expected by * the given group if possible. * * @param parameter The parameter for which the name is wanted. * @param group The group to use for determining the authority code space. * @return The name of the given parameter. * * @since 3.05 */ private static String getName(final GeneralParameterDescriptor parameter, final ParameterDescriptorGroup group) { String name = IdentifiedObjects.getName(parameter, group.getName().getAuthority()); if (name == null) { name = parameter.getName().getCode(); } return name; } /** * Returns the parameter value for the specified operation parameter. * * @param parameter The parameter to look for. * @param group The parameter value group to search into. * @return The requested parameter value. * @throws ParameterNotFoundException if the parameter is not found. */ private static ParameterValue getParameter(final ParameterDescriptor parameter, final ParameterValueGroup group) throws ParameterNotFoundException { /* * Searches for an identifier matching the group's authority, if any. * This is needed if the parameter values group was created from an * EPSG database for example: we need to use the EPSG names instead * of the OGC ones. */ final String name = getName(parameter, group.getDescriptor()); if (parameter.getMinimumOccurs() != 0) { return group.parameter(name); } /* * The parameter is optional. We don't want to invokes 'parameter(name)', because we don't * want to create a new parameter if the user didn't supplied one. Search the parameter * ourself (so we don't create any), and returns null if we don't find any. * * TODO: A simpler solution would be to add a 'isDefined' method in GeoAPI, * or something similar. */ final GeneralParameterDescriptor search; search = group.getDescriptor().descriptor(name); if (search instanceof ParameterDescriptor) { for (final GeneralParameterValue candidate : group.values()) { if (search.equals(candidate.getDescriptor())) { return (ParameterValue) candidate; } } } return null; } /** * Returns the value of the given parameter in the given group if defined, or create a * default parameter otherwise. This method is equivalent to: * * {@preformat java * return cast(group.parameter(parameter.getName().getCode())); * } * * except that this method tries to use an identifier of the same authority than the * given {@code group} if possible. * * @param parameter The parameter to look for. * @param group The parameter value group to search into. * @return The requested parameter object. * @throws ParameterNotFoundException if the parameter is not valid for the given group. * * @see ParameterValueGroup#parameter(String) * * @since 3.18 * @category query */ public static ParameterValue getOrCreate(final ParameterDescriptor parameter, final ParameterValueGroup group) throws ParameterNotFoundException { return cast(group.parameter(getName(parameter, group.getDescriptor())), parameter.getValueClass()); } /** * Returns the parameter value as an object for the given descriptor. * The method uses the {@link ParameterValue#getValue()} method for fetching the value. * * @param The type of the parameter value. * @param parameter The parameter to look for. * @param group The parameter value group to search into. * @return The requested parameter value, or {@code null} if the parameter * is optional and the user didn't provided any value. * @throws ParameterNotFoundException if the parameter is mandatory and not found in the group. * * @since 3.00 * @category query */ public static T value(final ParameterDescriptor parameter, final ParameterValueGroup group) throws ParameterNotFoundException { final ParameterValue value = getParameter(parameter, group); return (value != null) ? parameter.getValueClass().cast(value.getValue()) : null; } /** * Returns the parameter value as a string for the given descriptor. * This method uses the {@link ParameterValue#stringValue()} method for fetching the value. * Note that the result may be different than the above {@link #value value} method if the * {@code ParameterValue} implementation performs string conversions. * * @param parameter The parameter to look for. * @param group The parameter value group to search into. * @return The requested parameter value, or {@code null} if the parameter * is optional and the user didn't provided any value. * @throws ParameterNotFoundException if the parameter is mandatory and not found in the group. * * @category query * @since 3.00 */ public static String stringValue(final ParameterDescriptor parameter, final ParameterValueGroup group) throws ParameterNotFoundException { final ParameterValue value = getParameter(parameter, group); return (value != null) ? value.stringValue() : null; } /** * Returns the parameter value as a boolean for the given descriptor. * This method uses the {@link ParameterValue#booleanValue()} method for fetching the value. * Note that the result may be different than the above {@link #value value} method if the * {@code ParameterValue} implementation performs numeric conversions. * * @param parameter The parameter to look for. * @param group The parameter value group to search into. * @return The requested parameter value, or {@code null} if the parameter * is optional and the user didn't provided any value. * @throws ParameterNotFoundException if the parameter is mandatory and not found in the group. * * @category query * @since 3.18 */ public static Boolean booleanValue(final ParameterDescriptor parameter, final ParameterValueGroup group) throws ParameterNotFoundException { final ParameterValue value = getParameter(parameter, group); return (value != null) ? value.booleanValue() : null; } /** * Returns the parameter value as an integer for the given descriptor. * This method uses the {@link ParameterValue#intValue()} method for fetching the value. * Note that the result may be different than the above {@link #value value} method if the * {@code ParameterValue} implementation performs numeric conversions. * * @param parameter The parameter to look for. * @param group The parameter value group to search into. * @return The requested parameter value, or {@code null} if the parameter * is optional and the user didn't provided any value. * @throws ParameterNotFoundException if the parameter is mandatory and not found in the group. * * @category query * @since 3.00 */ public static Integer integerValue(final ParameterDescriptor parameter, final ParameterValueGroup group) throws ParameterNotFoundException { final ParameterValue value = getParameter(parameter, group); return (value != null) ? value.intValue() : null; } /** * Returns the parameter value as a list of integers for the given descriptor. * This method uses the {@link ParameterValue#intValueList()} method for fetching the values. * Note that the result may be different than the above {@link #value value} method if the * {@code ParameterValue} implementation performs numeric conversions. * * @param parameter The parameter to look for. * @param group The parameter value group to search into. * @return The requested parameter value, or {@code null} if the parameter * is optional and the user didn't provided any value. * @throws ParameterNotFoundException if the parameter is mandatory and not found in the group. * * @category query * @since 3.18 */ public static int[] integerValueList(final ParameterDescriptor parameter, final ParameterValueGroup group) throws ParameterNotFoundException { final ParameterValue value = getParameter(parameter, group); return (value != null) ? value.intValueList() : null; } /** * Returns the parameter value as a floating point number for the given descriptor. * Values are automatically converted into the standard units specified by the * supplied {@code param} argument. *

* This method uses the {@link ParameterValue#doubleValue(Unit)} method for fetching the value. * Note that the result may be different than the above {@link #value value} method if the * {@code ParameterValue} implementation performs numeric conversions. * * @param parameter The parameter to look for. * @param group The parameter value group to search into. * @return The requested parameter value, or {@code NaN} if the parameter * is optional and the user didn't provided any value. * @throws ParameterNotFoundException if the parameter is mandatory and not found in the group. * * @category query * @since 3.00 */ public static double doubleValue(final ParameterDescriptor parameter, final ParameterValueGroup group) throws ParameterNotFoundException { final Unit unit = parameter.getUnit(); final ParameterValue value = getParameter(parameter, group); return (value == null) ? Double.NaN : (unit != null) ? value.doubleValue(unit) : value.doubleValue(); } /** * Returns the parameter value as a list of floating point numbers for the given descriptor. * Values are automatically converted into the standard units specified by the * supplied {@code param} argument. *

* This method uses the {@link ParameterValue#doubleValueList(Unit)} method for fetching the * values. Note that the result may be different than the above {@link #value value} method * if the {@code ParameterValue} implementation performs numeric conversions. * * @param parameter The parameter to look for. * @param group The parameter value group to search into. * @return The requested parameter value, or {@code null} if the parameter * is optional and the user didn't provided any value. * @throws ParameterNotFoundException if the parameter is mandatory and not found in the group. * * @category query * @since 3.18 */ public static double[] doubleValueList(final ParameterDescriptor parameter, final ParameterValueGroup group) throws ParameterNotFoundException { final Unit unit = parameter.getUnit(); final ParameterValue value = getParameter(parameter, group); return (value == null) ? null : (unit != null) ? value.doubleValueList(unit) : value.doubleValueList(); } /** * Searches all parameters with the specified name. The given {@code name} is * compared against parameter {@linkplain GeneralParameterDescriptor#getName name} and * {@linkplain GeneralParameterDescriptor#getAlias alias}. This method search recursively * in subgroups up to the specified depth: *

*

    *
  • If {@code maxDepth} is equal to 0, then this method returns {@code param} * if and only if it matches the specified name.
  • *
  • If {@code maxDepth} is equal to 1 and {@code param} is an instance of * {@link ParameterDescriptorGroup}, then this method checks all elements * in this group but not in subgroups.
  • *
  • ...
  • *
  • If {@code maxDepth} is a high number (e.g. 100), then this method checks all elements * in all subgroups up to the specified depth, which is likely to be never reached. In * this case, {@code maxDepth} can be seen as a safeguard against never ending loops, for * example if parameters graph contains cyclic entries.
  • *
* * @param parameter The parameter to inspect. * @param name The name of the parameter to search for. See the * class javadoc for a rational about the usage * of name as a key instead of {@linkplain ParameterDescriptor descriptor}. * @param maxDepth The maximal depth while descending down the parameter tree. * @return The set (possibly empty) of parameters with the given name. * * @category query */ public static List search(final GeneralParameterValue parameter, final String name, int maxDepth) { final List list = new ArrayList(); search(parameter, name, maxDepth, list); return list; } /** * Implementation of the search algorithm. The result is stored in the supplied set. */ private static void search(final GeneralParameterValue parameter, final String name, final int maxDepth, final Collection list) { if (maxDepth >= 0) { if (IdentifiedObjects.nameMatches(parameter.getDescriptor(), name)) { list.add(parameter); } if ((maxDepth != 0) && (parameter instanceof ParameterValueGroup)) { for (final GeneralParameterValue value : ((ParameterValueGroup) parameter).values()) { search(value, name, maxDepth-1, list); } } } } /** * Gets the * {@linkplain ParameterDescriptor#getName name}-{@linkplain ParameterValue#getValue value} * pairs. This method copies all parameter values into the supplied {@code destination} map. * Keys are parameter names as {@link String} objects, and values are parameter values as * arbitrary objects. *

* If the given parameters is a group having sub-groups, then all subgroups are extracted * recursively with their keys prefixed by the sub-groups name followed by the * {@linkplain DefaultNameSpace#DEFAULT_SEPARATOR default namespace separator}. *

* This map provides a convenient way to copy the content of a {@link ParameterValueGroup} * to a {@link java.util.Properties} instance. * * @param parameters The parameters to extract values from. * @param destination The destination map. * * @category query * @since 3.18 */ public static void copy(final GeneralParameterValue parameters, final Map destination) { copy(parameters, destination, null, 0, true); } /** * Implementation of the public {@link #copy(GeneralParameterValue, Map)} method * for recursive invocations. * * @param parameters The parameters to extract values from. * @param destination The destination map. * @param buffer A buffer which contains the prefix of every keys, or {@code null}. * @param base The number of valid characters in the buffer. * @param isRoot {@code true} if the group to be added is the root, or {@code false} * on recursive invocations. * @return The buffer, which may have been created by some recursive invocation. * * @category query */ private static StringBuilder copy(final GeneralParameterValue parameters, final Map destination, StringBuilder buffer, int base, final boolean isRoot) { final String name = parameters.getDescriptor().getName().getCode(); if (parameters instanceof ParameterValue) { final Object value = ((ParameterValue) parameters).getValue(); String key = name; if (base > 0) { buffer.setLength(base); key = buffer.append(name).toString(); } final Object old = destination.put(key, value); if (old != null && !old.equals(value)) { // This code will fails to detect if a null value was explicitly supplied // previously. We assume that such case is uncommon and not a big deal. throw new IllegalArgumentException(Errors.format(Errors.Keys.INCONSISTENT_VALUE)); } } if (parameters instanceof ParameterValueGroup) { if (!isRoot) { if (buffer == null) { buffer = new StringBuilder(32); } buffer.setLength(base); base = buffer.append(name).append(DefaultNameSpace.DEFAULT_SEPARATOR).length(); } for (final GeneralParameterValue value : ((ParameterValueGroup) parameters).values()) { buffer = copy(value, destination, buffer, base, false); } } return buffer; } /** * Copies all parameter values from {@code source} to {@code target}. A typical usage of * this method is for transferring values from an arbitrary implementation to some specific * implementation (e.g. a parameter group implementation backed by a * {@link java.awt.image.renderable.ParameterBlock} for image processing operations). * * @param source The parameters to copy. * @param target Where to copy the source parameters. * * @category update * @since 2.2 */ public static void copy(final ParameterValueGroup source, final ParameterValueGroup target) { for (final GeneralParameterValue param : source.values()) { final String name = param.getDescriptor().getName().getCode(); if (param instanceof ParameterValueGroup) { copy((ParameterValueGroup) param, target.addGroup(name)); } else { target.parameter(name).setValue(((ParameterValue) param).getValue()); } } } /** * Ensures that a value is set for the parameter of the specified name. This method returns * {@code true} if the parameter value has been or should be changed (depending * on the {@code force} argument value), or {@code false} otherwise. * More specifically this method performs the following steps: *

*

    *
  • If the parameter for the given name has no value, unconditionally assign the given * value to that parameter and returns {@code true}.
  • *
  • Otherwise, compare the current parameter value with the specified value. * If the values are approximatively equal, do nothing and return {@code false}.
  • *
  • Otherwise there is a choice: *
      *
    • If the {@code force} argument is {@code true}, overwrite the current parameter * value with the given value.
    • *
    • Otherwise left the parameter value unchanged but log a warning.
    • *
    * Then return {@code true}.
  • *
*

* This method can used when the same parameter value may be specified more than once * (for example from different sources of information), and we want to ensure that all * those values are consistent, without treating mismatches as fatal errors. * * @param parameters The set of projection parameters. * @param name The parameter name to set. * @param value The value to set, or to expect if the parameter is already set. * @param unit The value unit. * @param force {@code true} for forcing the parameter to the specified {@code value} * is case of mismatch. * @return {@code true} if the were a mismatch (in which case the value has been updated if * the {@code force} argument is {@code true}), or {@code false} if the parameter * has been left unchanged. * @throws ParameterNotFoundException If no parameter of the given name has been found. * * @category update */ public static boolean ensureSet(final ParameterValueGroup parameters, final String name, final double value, final Unit unit, boolean force) throws ParameterNotFoundException { final ParameterValue parameter = parameters.parameter(name); try { final double current = parameter.doubleValue(unit); if (Math.abs(current / value - 1) <= EPS) { return false; } if (Double.isNaN(current)) { force = true; } } catch (IllegalStateException exception) { // No value was set for this parameter, and there is no default value. force = true; } // A value was set, but is different than the expected value. if (force) { parameter.setValue(value, unit); } else { Logging.log(Parameters.class, "ensureSet", new LogRecord(Level.FINE, Errors.format(Errors.Keys.VALUE_ALREADY_DEFINED_$1, name))); } return true; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy