001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2004, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation;
010: * version 2.1 of the License.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * This package contains documentation from OpenGIS specifications.
018: * OpenGIS consortium's work is fully acknowledged here.
019: */
020: package org.geotools.parameter;
021:
022: // J2SE dependencies and extensions
023: import java.net.URI;
024: import javax.units.Unit;
025:
026: // OpenGIS dependencies
027: import org.opengis.parameter.InvalidParameterTypeException;
028: import org.opengis.parameter.InvalidParameterValueException;
029: import org.opengis.parameter.ParameterDescriptor;
030: import org.opengis.parameter.ParameterValue;
031:
032: // Geotools dependencies
033: import org.geotools.resources.Utilities;
034: import org.geotools.resources.i18n.Errors;
035: import org.geotools.resources.i18n.ErrorKeys;
036:
037: /**
038: * A parameter value as a floating point (double precision) number.
039: * This class provides the same functionalities than {@link Parameter}, except that:
040: * <ul>
041: * <li>Values are always floating point numbers of type {@code double}.</li>
042: * <li>Units are the same than the {@linkplain ParameterDescriptor#getUnit default units}.</li>
043: * </ul>
044: * When those conditions are meet, {@code ParameterRealValue} is slightly more efficient
045: * than {@code ParameterValue} since it avoid the creation of {@link Double} objects.
046: *
047: * @since 2.1
048: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/parameter/FloatParameter.java $
049: * @version $Id: FloatParameter.java 20874 2006-08-07 10:00:01Z jgarnett $
050: * @author Martin Desruisseaux
051: *
052: * @see DefaultParameterDescriptor
053: * @see ParameterGroup
054: */
055: public class FloatParameter extends AbstractParameter implements
056: ParameterValue {
057: /**
058: * Serial number for interoperability with different versions.
059: */
060: private static final long serialVersionUID = 9027797654033417816L;
061:
062: /**
063: * The value.
064: */
065: private double value;
066:
067: /**
068: * Constructs a parameter from the specified descriptor. The descriptor
069: * {@linkplain ParameterDescriptor#getValueClass() value class}
070: * must be <code>{@linkplain Double}.class</code>.
071: *
072: * @param descriptor The abstract definition of this parameter.
073: * @throws IllegalArgumentException if the value class is not {@code Double.class}.
074: */
075: public FloatParameter(final ParameterDescriptor descriptor) {
076: super (descriptor);
077: final Class type = descriptor.getValueClass();
078: final Class expected = Double.class;
079: if (!expected.equals(type) && !Double.TYPE.equals(type)) {
080: throw new IllegalArgumentException(Errors.format(
081: ErrorKeys.ILLEGAL_CLASS_$2, Utilities
082: .getShortName(type), Utilities
083: .getShortName(expected)));
084: }
085: final Number value = (Number) descriptor.getDefaultValue();
086: this .value = (value != null) ? value.doubleValue() : Double.NaN;
087: }
088:
089: /**
090: * Constructs a parameter from the specified descriptor and value. This convenience
091: * constructor is equivalents to the one-argument constructor followed by a call to
092: * {@link #setValue(double)}.
093: *
094: * @param descriptor The abstract definition of this parameter.
095: * @param value The parameter value.
096: * @throws IllegalArgumentException if the value class is not {@code Double.class}.
097: */
098: public FloatParameter(final ParameterDescriptor descriptor,
099: final double value) {
100: this (descriptor);
101: setValue(value);
102: }
103:
104: /**
105: * Returns the unit of measure of the {@linkplain #doubleValue() parameter value}. The default
106: * implementation always delegates to {@link ParameterDescriptor#getUnit}.
107: *
108: * @return The unit of measure, or {@code null} if none.
109: */
110: public Unit getUnit() {
111: return ((ParameterDescriptor) descriptor).getUnit();
112: }
113:
114: /**
115: * Returns the numeric value of the coordinate operation parameter in the specified unit
116: * of measure. This convenience method apply unit conversion on the fly as needed.
117: *
118: * @param unit The unit of measure for the value to be returned.
119: * @return The numeric value represented by this parameter after conversion to type
120: * {@code double} and conversion to {@code unit}.
121: * @throws IllegalArgumentException if the specified unit is invalid for this parameter.
122: */
123: public double doubleValue(final Unit unit)
124: throws IllegalArgumentException {
125: ensureNonNull("unit", unit);
126: final Unit this Unit = getUnit();
127: if (this Unit == null) {
128: throw unitlessParameter(descriptor);
129: }
130: final int expectedID = Parameter.getUnitMessageID(this Unit);
131: if (Parameter.getUnitMessageID(unit) != expectedID) {
132: throw new IllegalArgumentException(Errors.format(
133: expectedID, unit));
134: }
135: return this Unit.getConverterTo(unit).convert(value);
136: }
137:
138: /**
139: * Returns the numeric value of the coordinate operation parameter with its
140: * associated {@linkplain #getUnit unit of measure}.
141: *
142: * @return The numeric value represented by this parameter after conversion to type {@code double}.
143: */
144: public double doubleValue() {
145: return value;
146: }
147:
148: /**
149: * Returns the numeric value rounded to the nearest integer.
150: *
151: * @return The numeric value represented by this parameter after conversion to type {@code int}.
152: */
153: public int intValue() {
154: return (int) Math.round(value);
155: }
156:
157: /**
158: * Returns {@code true} if the value is different from 0, {@code false} otherwise.
159: *
160: * @return The boolean value represented by this parameter.
161: */
162: public boolean booleanValue() {
163: return value != 0 && !Double.isNaN(value);
164: }
165:
166: /**
167: * Returns the string representation of the value.
168: *
169: * @return The string value represented by this parameter.
170: */
171: public String stringValue() {
172: return String.valueOf(value);
173: }
174:
175: /**
176: * Wraps the value in an array of length 1.
177: *
178: * @param unit The unit of measure for the value to be returned.
179: * @return The sequence of values represented by this parameter after conversion to type
180: * {@code double} and conversion to {@code unit}.
181: * @throws IllegalArgumentException if the specified unit is invalid for this parameter.
182: */
183: public double[] doubleValueList(final Unit unit)
184: throws IllegalArgumentException {
185: return new double[] { doubleValue(unit) };
186: }
187:
188: /**
189: * Wraps the value in an array of length 1.
190: *
191: * @return The sequence of values represented by this parameter.
192: */
193: public double[] doubleValueList() {
194: return new double[] { doubleValue() };
195: }
196:
197: /**
198: * Wraps the value in an array of length 1.
199: *
200: * @return The sequence of values represented by this parameter.
201: */
202: public int[] intValueList() {
203: return new int[] { intValue() };
204: }
205:
206: /**
207: * Always throws an exception, since this parameter is not an URI.
208: *
209: * @return Never return.
210: * @throws InvalidParameterTypeException The value is not a reference to a file or an URI.
211: */
212: public URI valueFile() throws InvalidParameterTypeException {
213: throw new InvalidParameterTypeException(getClassTypeError(),
214: Parameter.getName(descriptor));
215: }
216:
217: /**
218: * Format an error message for illegal method call for the current value type.
219: */
220: private static String getClassTypeError() {
221: return Errors.format(
222: ErrorKeys.ILLEGAL_OPERATION_FOR_VALUE_CLASS_$1,
223: "Double");
224: }
225:
226: /**
227: * Returns the parameter value as {{@link Double},
228: *
229: * @return The parameter value as an object.
230: */
231: public Object getValue() {
232: return new Double(value);
233: }
234:
235: /**
236: * Set the parameter value as a floating point and its associated unit.
237: *
238: * @param value The parameter value.
239: * @param unit The unit for the specified value.
240: * @throws InvalidParameterValueException if the value is illegal for some reason
241: * (for example a value out of range).
242: */
243: public void setValue(double value, final Unit unit)
244: throws InvalidParameterValueException {
245: ensureNonNull("unit", unit);
246: final Unit this Unit = ((ParameterDescriptor) descriptor)
247: .getUnit();
248: if (this Unit == null) {
249: throw unitlessParameter(descriptor);
250: }
251: final int expectedID = Parameter.getUnitMessageID(this Unit);
252: if (Parameter.getUnitMessageID(unit) != expectedID) {
253: throw new IllegalArgumentException(Errors.format(
254: expectedID, unit));
255: }
256: value = unit.getConverterTo(this Unit).convert(value);
257: Parameter.ensureValidValue((ParameterDescriptor) descriptor,
258: new Double(value));
259: this .value = value;
260: }
261:
262: /**
263: * Set the parameter value as a floating point.
264: *
265: * @param value The parameter value.
266: * @throws InvalidParameterValueException if the value is illegal for some reason
267: * (for example a value out of range).
268: */
269: public void setValue(final double value)
270: throws InvalidParameterValueException {
271: Parameter.ensureValidValue((ParameterDescriptor) descriptor,
272: new Double(value));
273: this .value = value;
274: }
275:
276: /**
277: * Set the parameter value as an integer.
278: *
279: * @param value The parameter value.
280: * @throws InvalidParameterValueException if the value is illegal for some reason
281: * (for example a value out of range).
282: */
283: public void setValue(final int value)
284: throws InvalidParameterValueException {
285: setValue((double) value);
286: }
287:
288: /**
289: * Set the parameter value as a boolean.
290: *
291: * @param value The parameter value.
292: * @throws InvalidParameterValueException if the boolean type is inappropriate for this parameter.
293: */
294: public void setValue(final boolean value)
295: throws InvalidParameterValueException {
296: setValue(value ? 1.0 : 0.0);
297: }
298:
299: /**
300: * Set the parameter value as a {@link Double} object.
301: *
302: * @param value The parameter value.
303: * @throws InvalidParameterValueException if the type of {@code value} is inappropriate
304: * for this parameter, or if the value is illegal for some other reason (for example
305: * the value is numeric and out of range).
306: */
307: public void setValue(final Object value)
308: throws InvalidParameterValueException {
309: Parameter.ensureValidValue((ParameterDescriptor) descriptor,
310: value);
311: this .value = ((Number) value).doubleValue();
312: }
313:
314: /**
315: * Always throws an exception, since this parameter is not an array.
316: */
317: public void setValue(double[] values, final Unit unit)
318: throws InvalidParameterValueException {
319: throw new InvalidParameterTypeException(getClassTypeError(),
320: Parameter.getName(descriptor));
321: }
322:
323: /**
324: * Compares the specified object with this parameter for equality.
325: *
326: * @param object The object to compare to {@code this}.
327: * @return {@code true} if both objects are equal.
328: */
329: public boolean equals(final Object object) {
330: if (super .equals(object)) {
331: final FloatParameter that = (FloatParameter) object;
332: return Double.doubleToLongBits(this .value) == Double
333: .doubleToLongBits(that.value);
334: }
335: return false;
336: }
337:
338: /**
339: * Returns a hash value for this parameter.
340: *
341: * @return The hash code value. This value doesn't need to be the same
342: * in past or future versions of this class.
343: */
344: public int hashCode() {
345: final long code = Double.doubleToLongBits(value);
346: return (int) code ^ (int) (code >>> 32) + super .hashCode() * 37;
347: }
348: }
|