You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2012/12/01 10:12:25 UTC
svn commit: r1415953 - in /sis/branches/JDK7/sis-utility/src:
main/java/org/apache/sis/io/ main/java/org/apache/sis/measure/
main/java/org/apache/sis/util/ main/java/org/apache/sis/util/resources/
test/java/org/apache/sis/measure/ test/java/org/apache/...
Author: desruisseaux
Date: Sat Dec 1 09:12:21 2012
New Revision: 1415953
URL: http://svn.apache.org/viewvc?rev=1415953&view=rev
Log:
Ported the Units class.
Added:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java (with props)
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Units.java (with props)
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/UnitsTest.java (with props)
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Workaround.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java Sat Dec 1 09:12:21 2012
@@ -380,7 +380,7 @@ public class TableFormatter extends Filt
public void setCellAlignment(final byte alignment) {
if (alignment < ALIGN_LEFT || alignment > ALIGN_RIGHT) {
throw new IllegalArgumentException(Errors.format(
- Errors.Keys.IllegalArgument_1, "alignment"));
+ Errors.Keys.IllegalArgumentValue_2, "alignment", alignment));
}
this.alignment = alignment;
}
Added: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java?rev=1415953&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java (added)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java Sat Dec 1 09:12:21 2012
@@ -0,0 +1,234 @@
+/*
+ * 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.measure;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.io.ObjectStreamException;
+import javax.measure.converter.UnitConverter;
+import net.jcip.annotations.Immutable;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Vocabulary;
+
+import static org.apache.sis.math.MathFunctions.truncate;
+
+
+/**
+ * A converter from fractional degrees to sexagesimal degrees. Sexagesimal degrees are pseudo-unit
+ * in the <cite>sign - degrees - decimal point - minutes (two digits) - integer seconds (two digits) -
+ * fraction of seconds (any precision)</cite> format.
+ *
+ * <p>When possible, Apache SIS always handles angles in radians, decimal degrees or any other
+ * proportional units. Sexagesimal angles are considered a string representation issue (handled
+ * by {@link AngleFormat}) rather than a unit issue. Unfortunately, this pseudo-unit is extensively
+ * used in the EPSG database, so we have to support it.</p>
+ *
+ * @author Martin Desruisseaux (IRD, Geomatys)
+ * @since 0.3 (derived from geotk-2.1)
+ * @version 0.3
+ * @module
+ */
+@Immutable // Intentionally not final.
+class SexagesimalConverter extends UnitConverter {
+ /**
+ * Serial number for compatibility with different versions.
+ */
+ private static final long serialVersionUID = 3873494343412121773L;
+
+ /**
+ * Small tolerance factor when comparing numbers close to 1.
+ * For comparing numbers other than 1, multiply by the number magnitude.
+ */
+ static final double EPS = 1E-10;
+
+ /**
+ * The converter for DMS units.
+ */
+ static final SexagesimalConverter INTEGER = new SexagesimalConverter(1);
+
+ /**
+ * The converter for D.MS units.
+ */
+ static final SexagesimalConverter FRACTIONAL = new SexagesimalConverter(10000);
+
+ /**
+ * The value to divide DMS unit by.
+ * For "degree minute second" (EPSG code 9107), this is 1.
+ * For "sexagesimal degree" (EPSG code 9110), this is 10000.
+ */
+ final int divider;
+
+ /**
+ * The inverse of this converter.
+ */
+ private final UnitConverter inverse;
+
+ /**
+ * Constructs a converter for sexagesimal units.
+ *
+ * @param divider The value to divide DMS unit by.
+ * For "degree minute second" (EPSG code 9107), this is 1.
+ * For "sexagesimal degree" (EPSG code 9110), this is 10000.
+ */
+ private SexagesimalConverter(final int divider) {
+ this.divider = divider;
+ this.inverse = new Inverse(this);
+ }
+
+ /**
+ * Constructs a converter for sexagesimal units.
+ * This constructor is for {@link Inverse} usage only.
+ */
+ private SexagesimalConverter(final int divider, final UnitConverter inverse) {
+ this.divider = divider;
+ this.inverse = inverse;
+ }
+
+ /**
+ * Returns the inverse of this converter.
+ */
+ @Override
+ public final UnitConverter inverse() {
+ return inverse;
+ }
+
+ /**
+ * Performs a conversion from fractional degrees to sexagesimal degrees.
+ */
+ @Override
+ public double convert(double angle) {
+ final double deg,min,sec; deg = truncate(angle);
+ angle = (angle-deg)*60; min = truncate(angle);
+ angle = (angle-min)*60; sec = truncate(angle);
+ angle -= sec; // The remainer (fraction of seconds)
+ return (((deg*100 + min)*100 + sec) + angle) / divider;
+ }
+
+ /**
+ * Performs a conversion from fractional degrees to sexagesimal degrees.
+ * This method delegates to the version working on {@code double} primitive type,
+ * so it does not provide the accuracy normally required by this method contract.
+ */
+ @Override
+ public final BigDecimal convert(final BigDecimal value, final MathContext context) {
+ return new BigDecimal(convert(value.doubleValue()), context);
+ }
+
+ /**
+ * Compares this converter with the specified object.
+ */
+ @Override
+ public final boolean equals(final Object object) {
+ return object != null && object.getClass() == getClass() &&
+ ((SexagesimalConverter) object).divider == divider;
+ }
+
+ /**
+ * Returns a hash value for this converter.
+ */
+ @Override
+ public int hashCode() {
+ return divider ^ (int) serialVersionUID;
+ }
+
+ /**
+ * On deserialization, returns an existing instance.
+ */
+ protected final Object readResolve() throws ObjectStreamException {
+ UnitConverter candidate = INTEGER;
+ for (int i=0; i<4; i++) {
+ switch (i) {
+ case 0: break; // Do nothing since candidate is already set to INTEGER.
+ case 1: // Fallthrough
+ case 3: candidate = candidate.inverse(); break;
+ case 2: candidate = FRACTIONAL; break;
+ }
+ if (equals(candidate)) {
+ return candidate;
+ }
+ }
+ return this;
+ }
+
+ /**
+ * The inverse of {@link SexagesimalConverter}.
+ */
+ @Immutable
+ private static final class Inverse extends SexagesimalConverter {
+ /**
+ * Serial number for compatibility with different versions.
+ */
+ private static final long serialVersionUID = -7171869900634417819L;
+
+ /**
+ * Constructs a converter.
+ */
+ public Inverse(final SexagesimalConverter inverse) {
+ super(inverse.divider, inverse);
+ }
+
+ /**
+ * Performs a conversion from sexagesimal degrees to fractional degrees.
+ *
+ * @throws IllegalArgumentException If the given angle can not be converted.
+ */
+ @Override
+ public double convert(final double angle) throws IllegalArgumentException {
+ double deg,min,sec;
+ sec = angle * divider;
+ deg = truncate(sec/10000); sec -= 10000*deg;
+ min = truncate(sec/ 100); sec -= 100*min;
+ if (min <= -60 || min >= 60) { // Do not enter for NaN
+ if (Math.abs(Math.abs(min) - 100) <= (EPS * 100)) {
+ if (min >= 0) deg++; else deg--;
+ min = 0;
+ } else {
+ throw illegalField(angle, min, Vocabulary.Keys.Minutes);
+ }
+ }
+ if (sec <= -60 || sec >= 60) { // Do not enter for NaN
+ if (Math.abs(Math.abs(sec) - 100) <= (EPS * 100)) {
+ if (sec >= 0) min++; else min--;
+ sec = 0;
+ } else {
+ throw illegalField(angle, sec, Vocabulary.Keys.Seconds);
+ }
+ }
+ return (sec/60 + min)/60 + deg;
+ }
+
+ /**
+ * Creates an exception for an illegal field.
+ *
+ * @param value The user-supplied angle value.
+ * @param field The value of the illegal field.
+ * @param unit The vocabulary key for the field (minutes or seconds).
+ * @return The exception to throw.
+ */
+ private static IllegalArgumentException illegalField(final double value, final double field, final int unit) {
+ return new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentField_4, "angle", value, unit, field));
+ }
+
+ /**
+ * Returns a hash value for this converter.
+ */
+ @Override
+ public int hashCode() {
+ return divider ^ (int) serialVersionUID;
+ }
+ }
+}
Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Units.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Units.java?rev=1415953&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Units.java (added)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Units.java Sat Dec 1 09:12:21 2012
@@ -0,0 +1,594 @@
+/*
+ * 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.measure;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import javax.measure.unit.SI;
+import javax.measure.unit.NonSI;
+import javax.measure.unit.Unit;
+import javax.measure.quantity.Angle;
+import javax.measure.quantity.Length;
+import javax.measure.quantity.Duration;
+import javax.measure.quantity.Dimensionless;
+import javax.measure.quantity.Quantity;
+import javax.measure.converter.UnitConverter;
+import org.apache.sis.util.Static;
+import org.apache.sis.util.Workaround;
+import org.apache.sis.util.Arrays;
+import org.apache.sis.util.Exceptions;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.resources.Errors;
+
+import static java.lang.Math.PI;
+import static java.lang.Math.abs;
+import static org.apache.sis.measure.SexagesimalConverter.EPS;
+import static org.apache.sis.util.CharSequences.trimWhitespaces;
+
+
+/**
+ * Static methods working on {@link Unit} instances, and some constants in addition to the
+ * {@link SI} and {@link NonSI} ones.
+ *
+ * @author Martin Desruisseaux (IRD, Geomatys)
+ * @since 0.3 (derived from geotk-2.1)
+ * @version 0.3
+ * @module
+ */
+public final class Units extends Static {
+ /**
+ * The suffixes that NetCDF files sometime put after the "degrees" unit.
+ * Suffix at even index are for axes having the standard geometric direction,
+ * while suffix at odd index are for axes having the reverse direction.
+ */
+ private static final String[] DEGREE_SUFFIXES = {"east", "west", "north", "south"};
+
+ /**
+ * Do not allows instantiation of this class.
+ */
+ private Units() {
+ }
+
+ /**
+ * Unit for milliseconds. Useful for conversion from and to {@link java.util.Date} objects.
+ */
+ public static final Unit<Duration> MILLISECOND = SI.MetricPrefix.MILLI(SI.SECOND);
+
+ /**
+ * Pseudo-unit for sexagesimal degree. Numbers in this pseudo-unit have the following format:
+ *
+ * <cite>sign - degrees - decimal point - minutes (two digits) - integer seconds (two digits) -
+ * fraction of seconds (any precision)</cite>.
+ *
+ * Using this unit is loosely equivalent to formatting decimal degrees with the
+ * {@code "D.MMSSs"} {@link AngleFormat} pattern.
+ *
+ * <p>This unit is non-linear and not practical for computation. Consequently, it should be
+ * avoided as much as possible. This pseudo-unit is defined only because extensively used in
+ * the EPSG database (code 9110).</p>
+ *
+ * <p>This unit does not have an easily readable symbol because of the
+ * <a href="http://kenai.com/jira/browse/JSR_275-41">JSR-275 bug</a>.</p>
+ */
+ static final Unit<Angle> SEXAGESIMAL_DMS = NonSI.DEGREE_ANGLE.transform(
+ SexagesimalConverter.FRACTIONAL.inverse()).asType(Angle.class);//.alternate("D.MS");
+
+ /**
+ * Pseudo-unit for degree - minute - second.
+ * Numbers in this pseudo-unit have the following format:
+ *
+ * <cite>signed degrees (integer) - arc-minutes (integer) - arc-seconds
+ * (real, any precision)</cite>.
+ *
+ * Using this unit is loosely equivalent to formatting decimal degrees with the
+ * {@code "DMMSS.s"} {@link AngleFormat} pattern.
+ *
+ * <p>This unit is non-linear and not practical for computation. Consequently, it should be
+ * avoided as much as possible. This pseudo-unit is defined only because extensively used in
+ * EPSG database (code 9107).</p>
+ *
+ * <p>This unit does not have an easily readable symbol because of the
+ * <a href="http://kenai.com/jira/browse/JSR_275-41">JSR-275 bug</a>.</p>
+ */
+ static final Unit<Angle> DEGREE_MINUTE_SECOND = NonSI.DEGREE_ANGLE.transform(
+ SexagesimalConverter.INTEGER.inverse()).asType(Angle.class);//.alternate("DMS");
+
+ /**
+ * Parts per million.
+ *
+ * <p>This unit does not have an easily readable symbol because of the
+ * <a href="http://kenai.com/jira/browse/JSR_275-41">JSR-275 bug</a>.</p>
+ */
+ public static final Unit<Dimensionless> PPM = Unit.ONE.times(1E-6);//.alternate("ppm");
+
+ /**
+ * A few units commonly used in GIS.
+ */
+ private static final Map<Unit<?>,Unit<?>> COMMONS = new HashMap<>(48);
+ static {
+ COMMONS.put(PPM, PPM);
+ boolean nonSI = false;
+ do for (final Field field : (nonSI ? NonSI.class : SI.class).getFields()) {
+ final int modifiers = field.getModifiers();
+ if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
+ final Object value;
+ try {
+ value = field.get(null);
+ } catch (ReflectiveOperationException e) {
+ // Should not happen since we asked only for public static constants.
+ throw new AssertionError(e);
+ }
+ if (value instanceof Unit<?>) {
+ final Unit<?> unit = (Unit<?>) value;
+ if (isLinear(unit) || isAngular(unit) || isScale(unit)) {
+ COMMONS.put(unit, unit);
+ }
+ }
+ }
+ } while ((nonSI = !nonSI) == true);
+ }
+
+ /**
+ * Returns {@code true} if the given unit is a linear unit.
+ * Linear units are convertible to {@link NonSI#DEGREE_ANGLE}.
+ *
+ * <p>Angular units are dimensionless, which may be a cause of confusion with other
+ * dimensionless units like {@link Unit#ONE} or {@link #PPM}. This method take care
+ * of differentiating angular units from other dimensionless units.</p>
+ *
+ * @param unit The unit to check (may be {@code null}).
+ * @return {@code true} if the given unit is non-null and angular.
+ *
+ * @see #ensureAngular(Unit)
+ */
+ public static boolean isAngular(final Unit<?> unit) {
+ return (unit != null) && unit.toSI().equals(SI.RADIAN);
+ }
+
+ /**
+ * Returns {@code true} if the given unit is a linear unit.
+ * Linear units are convertible to {@link SI#METRE}.
+ *
+ * @param unit The unit to check (may be {@code null}).
+ * @return {@code true} if the given unit is non-null and linear.
+ *
+ * @see #ensureLinear(Unit)
+ */
+ public static boolean isLinear(final Unit<?> unit) {
+ return (unit != null) && unit.toSI().equals(SI.METRE);
+ }
+
+ /**
+ * Returns {@code true} if the given unit is a pressure unit.
+ * Pressure units are convertible to {@link SI#PASCAL}.
+ * Those units are sometime used instead of linear units for altitude measurements.
+ *
+ * @param unit The unit to check (may be {@code null}).
+ * @return {@code true} if the given unit is non-null and a pressure unit.
+ */
+ public static boolean isPressure(final Unit<?> unit) {
+ return (unit != null) && unit.toSI().equals(SI.PASCAL);
+ }
+
+ /**
+ * Returns {@code true} if the given unit is a temporal unit.
+ * Temporal units are convertible to {@link SI#SECOND}.
+ *
+ * @param unit The unit to check (may be {@code null}).
+ * @return {@code true} if the given unit is non-null and temporal.
+ *
+ * @see #ensureTemporal(Unit)
+ */
+ public static boolean isTemporal(final Unit<?> unit) {
+ return (unit != null) && unit.toSI().equals(SI.SECOND);
+ }
+
+ /**
+ * Returns {@code true} if the given unit is a dimensionless scale unit.
+ * This include {@link Unit#ONE} and {@link #PPM}.
+ *
+ * @param unit The unit to check (may be {@code null}).
+ * @return {@code true} if the given unit is non-null and a dimensionless scale.
+ *
+ * @see #ensureScale(Unit)
+ */
+ public static boolean isScale(final Unit<?> unit) {
+ return (unit != null) && unit.toSI().equals(Unit.ONE);
+ }
+
+ /**
+ * Makes sure that the specified unit is either null or an angular unit.
+ * This method is used for argument checks in constructors and setter methods.
+ *
+ * @param unit The unit to check, or {@code null}Â if none.
+ * @return The given {@code unit} argument, which may be null.
+ * @throws IllegalArgumentException if {@code unit} is non-null and not an angular unit.
+ *
+ * @see #isAngular(Unit)
+ */
+ @SuppressWarnings({"unchecked","rawtypes"})
+ public static Unit<Angle> ensureAngular(final Unit<?> unit) throws IllegalArgumentException {
+ if (unit != null && !isAngular(unit)) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.NonAngularUnit_1, unit));
+ }
+ return (Unit) unit;
+ }
+
+ /**
+ * Makes sure that the specified unit is either null or a linear unit.
+ * This method is used for argument checks in constructors and setter methods.
+ *
+ * @param unit The unit to check, or {@code null}Â if none.
+ * @return The given {@code unit} argument, which may be null.
+ * @throws IllegalArgumentException if {@code unit} is non-null and not a linear unit.
+ *
+ * @see #isLinear(Unit)
+ */
+ @SuppressWarnings({"unchecked","rawtypes"})
+ public static Unit<Length> ensureLinear(final Unit<?> unit) throws IllegalArgumentException {
+ if (unit != null && !isLinear(unit)) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.NonLinearUnit_1, unit));
+ }
+ return (Unit) unit;
+ }
+
+ /**
+ * Makes sure that the specified unit is either null or a temporal unit.
+ * This method is used for argument checks in constructors and setter methods.
+ *
+ * @param unit The unit to check, or {@code null}Â if none.
+ * @return The given {@code unit} argument, which may be null.
+ * @throws IllegalArgumentException if {@code unit} is non-null and not a temporal unit.
+ *
+ * @see #isTemporal(Unit)
+ */
+ @SuppressWarnings({"unchecked","rawtypes"})
+ public static Unit<Duration> ensureTemporal(final Unit<?> unit) throws IllegalArgumentException {
+ if (unit != null && !isTemporal(unit)) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.NonTemporalUnit_1, unit));
+ }
+ return (Unit) unit;
+ }
+
+ /**
+ * Makes sure that the specified unit is either null or a scale unit.
+ * This method is used for argument checks in constructors and setter methods.
+ *
+ * @param unit The unit to check, or {@code null}Â if none.
+ * @return The given {@code unit} argument, which may be null.
+ * @throws IllegalArgumentException if {@code unit} is non-null and not a scale unit.
+ *
+ * @see #isScale(Unit)
+ */
+ @SuppressWarnings({"unchecked","rawtypes"})
+ public static Unit<Dimensionless> ensureScale(final Unit<?> unit) throws IllegalArgumentException {
+ if (unit != null && !isScale(unit)) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.NonScaleUnit_1, unit));
+ }
+ return (Unit) unit;
+ }
+
+ /**
+ * Multiplies the given unit by the given factor. For example multiplying {@link SI#METRE}
+ * by 1000 gives {@link SI#KILOMETRE}. Invoking this method is equivalent to invoking
+ * {@link Unit#times(double)} except for the following:
+ *
+ * <ul>
+ * <li>A small tolerance factor is applied for a few factors commonly used in GIS.
+ * For example {@code multiply(SI.RADIANS, 0.0174532925199...)} will return
+ * {@link NonSI#DEGREE_ANGLE} even if the given numerical value is slightly
+ * different than {@linkplain Math#PI pi}/180. The tolerance factor and the
+ * set of units handled especially may change in future SIS versions.</li>
+ * <li>This method tries to returns unique instances for some common units.</li>
+ * </ul>
+ *
+ * @param <A> The quantity measured by the unit.
+ * @param unit The unit to multiply.
+ * @param factor The multiplication factor.
+ * @return The unit multiplied by the given factor.
+ */
+ @Workaround(library="JSR-275", version="0.9.3")
+ @SuppressWarnings({"unchecked","rawtypes"})
+ public static <A extends Quantity> Unit<A> multiply(Unit<A> unit, final double factor) {
+ if (SI.RADIAN.equals(unit)) {
+ if (abs(factor - (PI / 180)) <= (EPS * PI/180)) {
+ return (Unit) NonSI.DEGREE_ANGLE;
+ }
+ if (abs(factor - (PI / 200)) <= (EPS * PI/200)) {
+ return (Unit) NonSI.GRADE;
+ }
+ }
+ if (abs(factor - 1) > EPS) {
+ final long fl = (long) factor;
+ if (fl == factor) {
+ /*
+ * Invoke the Unit.times(long) overloaded method, not Unit.scale(double),
+ * because as of JSR-275 0.9.3 the method with the long argument seems to
+ * do a better work of detecting when the result is an existing unit.
+ */
+ unit = unit.times(fl);
+ } else {
+ unit = unit.times(factor);
+ }
+ }
+ return canonicalize(unit);
+ }
+
+ /**
+ * Returns a unique instance of the given units if possible, or the units unchanged otherwise.
+ *
+ * @param <A> The quantity measured by the unit.
+ * @param unit The unit to canonicalize.
+ * @return A unit equivalents to the given unit, canonicalized if possible.
+ */
+ @SuppressWarnings({"unchecked","rawtypes"})
+ private static <A extends Quantity> Unit<A> canonicalize(final Unit<A> unit) {
+ final Unit<?> candidate = COMMONS.get(unit);
+ if (candidate != null) {
+ return (Unit) candidate;
+ }
+ return unit;
+ }
+
+ /**
+ * Returns the factor by which to multiply the standard unit in order to get the given unit.
+ * The "standard" unit is usually the SI unit on which the given unit is based.
+ *
+ * <p><b>Example:</b> If the given unit is <var>kilometre</var>, then this method returns 1000
+ * since a measurement in kilometres must be multiplied by 1000 in order to give the equivalent
+ * measurement in the "standard" units (here <var>metres</var>).</p>
+ *
+ * @param <A> The quantity measured by the unit.
+ * @param unit The unit for which we want the multiplication factor to standard unit.
+ * @return The factor by which to multiply a measurement in the given unit in order to
+ * get an equivalent measurement in the standard unit.
+ */
+ @Workaround(library="JSR-275", version="0.9.3")
+ public static <A extends Quantity> double toStandardUnit(final Unit<A> unit) {
+ return derivative(unit.getConverterTo(unit.toSI()), 0);
+ }
+
+ /**
+ * Returns an estimation of the derivative of the given converter at the given value.
+ * This method is a workaround for a method which existed in previous JSR-275 API but
+ * have been removed in more recent releases. This method will be deprecated if the
+ * removed API is reinserted in future JSR-275 release.
+ *
+ * <p>Current implementation computes the derivative as below:</p>
+ *
+ * {@preformat java
+ * return converter.convert(value + 1) - converter.convert(value);
+ * }
+ *
+ * The above is exact for {@linkplain javax.measure.converter.LinearConverter linear converters},
+ * which is the case of the vast majority of unit converters in use. It may not be exact for a
+ * few unusual converter like the one from {@link #SEXAGESIMAL_DMS} to decimal degrees for
+ * example.
+ *
+ * @param converter The converter for which we want the derivative at a given point.
+ * @param value The point at which to compute the derivative.
+ * @return The derivative at the given point.
+ */
+ @Workaround(library="JSR-275", version="0.9.3")
+ public static double derivative(final UnitConverter converter, final double value) {
+ return converter.convert(value + 1) - converter.convert(value);
+ }
+
+ /**
+ * Parses the given symbol. This method is similar to {@link Unit#valueOf(CharSequence)}, but
+ * hands especially a few symbols found in WKT parsing or in XML files. The list of symbols
+ * handled especially is implementation-dependent and may change in future SIS versions.
+ *
+ * {@section Parsing authority codes}
+ * As a special case, if the given {@code uom} arguments is of the form {@code "EPSG:xxx"}
+ * (ignoring case and whitespaces), then {@code "xxx"} is parsed as an integer and forwarded
+ * to the {@link #valueOfEPSG(int)} method.
+ *
+ * {@section NetCDF unit symbols}
+ * The attributes in NetCDF files often merge the axis direction with the angular unit,
+ * as in {@code "degrees_east"} or {@code "degrees_north"}. This {@code valueOf} method
+ * ignores those suffixes and unconditionally returns {@link NonSI#DEGREE_ANGLE} for all
+ * axis directions. In particular, the units for {@code "degrees_west"} and {@code "degrees_east"}
+ * do <strong>not</strong> have opposite sign. It is caller responsibility to handle the
+ * direction of axes associated to NetCDF units.
+ *
+ * @param uom The symbol to parse, or {@code null}.
+ * @return The parsed symbol, or {@code null} if {@code uom} was null.
+ * @throws IllegalArgumentException if the given symbol can not be parsed.
+ */
+ public static Unit<?> valueOf(String uom) throws IllegalArgumentException {
+ if (uom == null) {
+ return null;
+ }
+ uom = trimWhitespaces(CharSequences.toASCII(uom)).toString();
+ final int length = uom.length();
+ /*
+ * Check for authority codes (currently only EPSG, but more could be added later).
+ * If the unit is not an authority code (which is the most common case), then we
+ * will check for hard-coded unit symbols.
+ */
+ int s = uom.indexOf(':');
+ if (s >= 0) {
+ final String authority = (String) trimWhitespaces(uom, 0, s);
+ if (authority.equalsIgnoreCase("EPSG")) try {
+ return valueOfEPSG(Integer.parseInt((String) trimWhitespaces(uom, s+1, length)));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(Errors.format(
+ Errors.Keys.IllegalArgumentValue_2, "uom", uom), e);
+ }
+ }
+ /*
+ * Check for degrees units. Note that "deg" could be both angular and Celsius degrees.
+ * We try to resolve this ambiguity in the code below by looking for the "Celsius" suffix.
+ * Other suffixes commonly found in NetCDF files are "west", "east", "north" or "south".
+ * Those suffixes are ignored.
+ */
+ if (uom.regionMatches(true, 0, "deg", 0, 3)) {
+ if (length == 3) {
+ return NonSI.DEGREE_ANGLE; // Exactly "deg"
+ }
+ String prefix = uom;
+ boolean isTemperature = false;
+ s = Math.max(uom.lastIndexOf(' '), uom.lastIndexOf('_'));
+ if (s >= 1) {
+ final String suffix = (String) trimWhitespaces(uom, s+1, length);
+ if (Arrays.containsIgnoreCase(DEGREE_SUFFIXES, suffix) || (isTemperature = isCelsius(suffix))) {
+ prefix = (String) trimWhitespaces(uom, 0, s); // Remove the suffix only if we recognized it.
+ }
+ }
+ if (equalsIgnorePlural(prefix, "degree")) {
+ return isTemperature ? SI.CELSIUS : NonSI.DEGREE_ANGLE;
+ }
+ } else {
+ /*
+ * Check for unit symbols that do not begin with "deg". If a symbol begins
+ * with "deg", then the check should be put in the above block instead.
+ */
+ if (uom.equals("°") || equalsIgnorePlural(uom, "decimal_degree")) return NonSI.DEGREE_ANGLE;
+ if (uom.equalsIgnoreCase("rad") || equalsIgnorePlural(uom, "radian")) return SI.RADIAN;
+ if (equalsIgnorePlural(uom, "kilometer") || equalsIgnorePlural(uom, "kilometre")) return SI.KILOMETRE;
+ if (equalsIgnorePlural(uom, "meter") || equalsIgnorePlural(uom, "metre")) return SI.METRE;
+ if (equalsIgnorePlural(uom, "week")) return NonSI.WEEK;
+ if (equalsIgnorePlural(uom, "day")) return NonSI.DAY;
+ if (equalsIgnorePlural(uom, "hour")) return NonSI.HOUR;
+ if (equalsIgnorePlural(uom, "minute")) return NonSI.MINUTE;
+ if (equalsIgnorePlural(uom, "second")) return SI .SECOND;
+ if (equalsIgnorePlural(uom, "pixel")) return NonSI.PIXEL;
+ if (isCelsius(uom)) return SI.CELSIUS;
+ if (uom.isEmpty() ||
+ uom.equalsIgnoreCase("psu") || // Pratical Salinity Scale (oceanography)
+ uom.equalsIgnoreCase("level")) // Sigma level (oceanography)
+ {
+ return Unit.ONE;
+ }
+ }
+ final Unit<?> unit;
+ try {
+ unit = Unit.valueOf(uom);
+ } catch (IllegalArgumentException e) {
+ // Provides a better error message than the default JSR-275 0.9.4 implementation.
+ throw Exceptions.setMessage(e, Errors.format(Errors.Keys.IllegalArgumentValue_2, "uom", uom), true);
+ }
+ return canonicalize(unit);
+ }
+
+ /**
+ * Returns {@code true} if the given {@code uom} is equals to the given expected string,
+ * ignoring trailing {@code 's'} character (if any).
+ */
+ @SuppressWarnings("fallthrough")
+ private static boolean equalsIgnorePlural(final String uom, final String expected) {
+ final int length = expected.length();
+ switch (uom.length() - length) {
+ case 0: break; // uom has exactly the expected length.
+ case 1: if (Character.toLowerCase(uom.charAt(length)) == 's') break; // else fallthrough.
+ default: return false;
+ }
+ return uom.regionMatches(true, 0, expected, 0, length);
+ }
+
+ /**
+ * Returns {@code true} if the given {@code uom} is equals to {@code "Celsius"} or
+ * {@code "Celcius"}. The later is a common misspelling.
+ */
+ private static boolean isCelsius(final String uom) {
+ return uom.equalsIgnoreCase("Celsius") || uom.equalsIgnoreCase("Celcius");
+ }
+
+ /**
+ * Returns a hard-coded unit from an EPSG code. The {@code code} argument given to this
+ * method shall be a code identifying a record in the {@code "Unit of Measure"} table of
+ * the EPSG database. If this method does not recognize the given code, then it returns
+ * {@code null}.
+ *
+ * <p>The list of units recognized by this method is not exhaustive. This method recognizes
+ * the base units declared in the {@code [TARGET_UOM_CODE]} column of the above-cited table,
+ * and some frequently-used units. The list of recognized units may be updated in any future
+ * version of SIS.</p>
+ *
+ * <p>The {@link org.apache.sis.referencing.factory.epsg.DirectEpsgFactory} uses this method
+ * for fetching the base units, and derives automatically other units from the information
+ * found in the EPSG database. This method is also used by other code not directly related
+ * to the EPSG database, like {@link org.apache.sis.referencing.factory.web.AutoCRSFactory}
+ * which uses EPSG code for identifying units.</p>
+ *
+ * <p>The values currently recognized are:</p>
+ * <table class="sis">
+ * <tr>
+ * <th>Linear units</th>
+ * <th class="sep">Angular units</th>
+ * <th class="sep">Scale units</th>
+ * </tr><tr>
+ * <td><table class="compact">
+ * <tr><td width="40"><b>Code</b></td><td><b>Unit</b></td></tr>
+ * <tr><td>9001</td><td>metre</td></tr>
+ * <tr><td>9002</td><td>foot</td></tr>
+ * <tr><td>9030</td><td>nautical mile</td></tr>
+ * <tr><td>9036</td><td>kilometre</td></tr>
+ * </table></td>
+ * <td class="sep"><table class="compact">
+ * <tr><td width="40"><b>Code</b></td><td><b>Unit</b></td></tr>
+ * <tr><td>9101</td><td>radian</td></tr>
+ * <tr><td>9102</td><td>decimal degree</td></tr>
+ * <tr><td>9103</td><td>minute</td></tr>
+ * <tr><td>9104</td><td>second</td></tr>
+ * <tr><td>9105</td><td>grade</td></tr>
+ * <tr><td>9107</td><td>degree-minute-second</td></tr>
+ * <tr><td>9108</td><td>degree-minute-second</td></tr>
+ * <tr><td>9109</td><td>microradian</td></tr>
+ * <tr><td>9110</td><td>sexagesimal degree-minute-second</td></tr>
+ * <tr><td>9111</td><td>sexagesimal degree-minute</td></tr>
+ * <tr><td>9122</td><td>decimal degree</td></tr>
+ * </table></td>
+ * <td class="sep"><table class="compact">
+ * <tr><td width="40"><b>Code</b></td><td><b>Unit</b></td></tr>
+ * <tr><td>9201</td><td>one</td></tr>
+ * <tr><td>9202</td><td>part per million</td></tr>
+ * <tr><td>9203</td><td>one</td></tr>
+ * </table></td>
+ * </tr>
+ * </table>
+ *
+ * @param code The EPSG code for a unit of measurement.
+ * @return The unit, or {@code null} if the code is unrecognized.
+ */
+ public static Unit<?> valueOfEPSG(final int code) {
+ switch (code) {
+ case 9001: return SI .METRE;
+ case 9002: return NonSI.FOOT;
+ case 9030: return NonSI.NAUTICAL_MILE;
+ case 9036: return SI .KILOMETRE;
+ case 9101: return SI .RADIAN;
+ case 9122: // Fall through
+ case 9102: return NonSI.DEGREE_ANGLE;
+ case 9103: return NonSI.MINUTE_ANGLE;
+ case 9104: return NonSI.SECOND_ANGLE;
+ case 9105: return NonSI.GRADE;
+ case 9107: return Units.DEGREE_MINUTE_SECOND;
+ case 9108: return Units.DEGREE_MINUTE_SECOND;
+ case 9109: return SI.MetricPrefix.MICRO(SI.RADIAN);
+ case 9111: // Sexagesimal DM: use DMS.
+ case 9110: return Units.SEXAGESIMAL_DMS;
+ case 9203: // Fall through
+ case 9201: return Unit .ONE;
+ case 9202: return Units.PPM;
+ default: return null;
+ }
+ }
+}
Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Units.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/Units.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java Sat Dec 1 09:12:21 2012
@@ -27,25 +27,46 @@ import org.apache.sis.util.resources.Err
* Every methods in this class can throw one of the following exceptions:
*
* <table class="sis">
- * <tr><th>Exception</th><th class="sep">Thrown by</th></tr>
- * <tr><td>{@link NullArgumentException}</td>
- * <td class="sep">{@link #ensureNonNull(String, Object) ensureNonNull},
- * {@link #ensureNonEmpty(String, CharSequence) ensureNonEmpty}</td></tr>
- *
- * <tr><td>{@link IllegalArgumentException}</td>
- * <td class="sep">{@link #ensureNonEmpty(String, CharSequence) ensureNonEmpty},
- * {@link #ensurePositive(String, int) ensurePositive},
- * {@link #ensureStrictlyPositive(String, int) ensureStrictlyPositive},
- * {@link #ensureBetween(String, int, int, int) ensureBetween},
- * {@link #ensureCanCast(String, Class, Object) ensureCanCast}</td></tr>
- *
- * <tr><td>{@link IndexOutOfBoundsException}</td>
- * <td class="sep">{@link #ensureValidIndex(int, int) ensureValidIndex}</td></tr>
- *
- * <tr><td>{@link MismatchedDimensionException}</td>
- * <td class="sep">{@link #ensureDimensionMatches(String, int, DirectPosition) ensureDimensionMatches}</td></tr>
+ * <tr>
+ * <th>Exception</th>
+ * <th class="sep">Thrown by</th>
+ * </tr><tr>
+ * <td>{@link NullArgumentException}</td>
+ * <td class="sep">
+ * {@link #ensureNonNull(String, Object) ensureNonNull},
+ * {@link #ensureNonEmpty(String, CharSequence) ensureNonEmpty}.
+ * </td>
+ * </tr><tr>
+ * <td>{@link IllegalArgumentException}</td>
+ * <td class="sep">
+ * {@link #ensureNonEmpty(String, CharSequence) ensureNonEmpty},
+ * {@link #ensurePositive(String, int) ensurePositive},
+ * {@link #ensureStrictlyPositive(String, int) ensureStrictlyPositive},
+ * {@link #ensureBetween(String, int, int, int) ensureBetween},
+ * {@link #ensureCanCast(String, Class, Object) ensureCanCast}.
+ * </td>
+ * </tr><tr>
+ * <td>{@link IndexOutOfBoundsException}</td>
+ * <td class="sep">
+ * {@link #ensureValidIndex(int, int) ensureValidIndex}.
+ * </td>
+ * </tr><tr>
+ * <td>{@link MismatchedDimensionException}</td>
+ * <td class="sep">
+ * {@link #ensureDimensionMatches(String, int, DirectPosition) ensureDimensionMatches}.
+ * </td>
+ * </tr>
* </table>
*
+ * More specialized {@code ensureXXX(â¦)} methods are provided in the following classes:
+ * <ul>
+ * <li>{@link org.apache.sis.measure.Units}:
+ * {@link org.apache.sis.measure.Units#ensureAngular ensureAngular},
+ * {@link org.apache.sis.measure.Units#ensureLinear ensureLinear},
+ * {@link org.apache.sis.measure.Units#ensureTemporal ensureTemporal},
+ * {@link org.apache.sis.measure.Units#ensureScale ensureScale}.</li>
+ * </ul>
+ *
* {@section Method Arguments}
* By convention, the value to check is always the last parameter given to every methods
* in this class. The other parameters may include the programmatic name of the argument
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Workaround.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Workaround.java?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Workaround.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Workaround.java Sat Dec 1 09:12:21 2012
@@ -16,6 +16,7 @@
*/
package org.apache.sis.util;
+import java.lang.annotation.Documented;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import java.lang.annotation.ElementType;
@@ -36,6 +37,7 @@ import java.lang.annotation.RetentionPol
* @version 0.3
* @module
*/
+@Documented
@Target({ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD,
ElementType.FIELD, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java Sat Dec 1 09:12:21 2012
@@ -100,14 +100,15 @@ public final class Errors extends Indexe
public static final int IllegalArgumentClass_3 = 2;
/**
- * Argument â{0}â can not take the â{1}â value.
+ * Argument â{0}â can not take the â{1}â value, because the â{2}â field can not take the â{3}â
+ * value.
*/
- public static final int IllegalArgumentValue_2 = 14;
+ public static final int IllegalArgumentField_4 = 15;
/**
- * Illegal value for argument â{0}â.
+ * Argument â{0}â can not take the â{1}â value.
*/
- public static final int IllegalArgument_1 = 15;
+ public static final int IllegalArgumentValue_2 = 14;
/**
* Illegal bits pattern: {0}.
@@ -190,6 +191,26 @@ public final class Errors extends Indexe
public static final int NodeNotFound_1 = 39;
/**
+ * â{0}â is not an angular unit.
+ */
+ public static final int NonAngularUnit_1 = 46;
+
+ /**
+ * â{0}â is not a linear unit.
+ */
+ public static final int NonLinearUnit_1 = 47;
+
+ /**
+ * â{0}â is not a scale unit.
+ */
+ public static final int NonScaleUnit_1 = 48;
+
+ /**
+ * â{0}â is not a time unit.
+ */
+ public static final int NonTemporalUnit_1 = 49;
+
+ /**
* Argument â{0}â shall not be NaN (Not-a-Number).
*/
public static final int NotANumber_1 = 9;
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties Sat Dec 1 09:12:21 2012
@@ -21,9 +21,9 @@ DuplicatedValue_1 = Value
ElementAlreadyPresent_1 = Element \u201c{0}\u201d is already present.
EmptyArgument_1 = Argument \u2018{0}\u2019 shall not be empty.
ForbiddenAttribute_2 = Attribute \u201c{0}\u201d is not allowed for an object of type \u2018{1}\u2019.
-IllegalArgument_1 = Illegal value for argument \u2018{0}\u2019.
IllegalArgumentClass_2 = Argument \u2018{0}\u2019 can not be an instance of \u2018{1}\u2019.
IllegalArgumentClass_3 = Argument \u2018{0}\u2019 can not be an instance of \u2018{1}\u2019. Expected an instance of \u2018{2}\u2019 or derived type.
+IllegalArgumentField_4 = Argument \u2018{0}\u2019 can not take the \u201c{1}\u201d value, because the \u2018{2}\u2019 field can not take the \u201c{3}\u201d value.
IllegalArgumentValue_2 = Argument \u2018{0}\u2019 can not take the \u201c{1}\u201d value.
IllegalBitsPattern_1 = Illegal bits pattern: {0}.
IllegalClass_2 = Class \u2018{0}\u2019 is illegal. It must be \u2018{1}\u2019 or a derived class.
@@ -41,6 +41,10 @@ NodeChildOfItself_1 = Node \
NodeHasAnotherParent_1 = Node \u201c{0}\u201d already has another parent.
NodeHasNoParent_1 = Node \u201c{0}\u201d has no parent.
NodeNotFound_1 = No \u201c{0}\u201d node found.
+NonAngularUnit_1 = \u201c{0}\u201d is not an angular unit.
+NonLinearUnit_1 = \u201c{0}\u201d is not a linear unit.
+NonScaleUnit_1 = \u201c{0}\u201d is not a scale unit.
+NonTemporalUnit_1 = \u201c{0}\u201d is not a time unit.
NotANumber_1 = Argument \u2018{0}\u2019 shall not be NaN (Not-a-Number).
NotAPrimitiveWrapper_1 = Class \u2018{0}\u2019 is not a primitive type wrapper.
NullArgument_1 = Argument \u2018{0}\u2019 shall not be null.
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties Sat Dec 1 09:12:21 2012
@@ -21,9 +21,9 @@ DuplicatedValue_1 = La val
ElementAlreadyPresent_1 = L\u2019\u00e9lement \u201c{0}\u201d est d\u00e9j\u00e0 pr\u00e9sent.
EmptyArgument_1 = L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre vide.
ForbiddenAttribute_2 = L\u2019attribut \u201c{0}\u201d n\u2019est pas autoris\u00e9 pour un objet de type \u2018{1}\u2019.
-IllegalArgument_1 = Valeur ill\u00e9gale pour l\u2019argument \u2018{0}\u2019.
IllegalArgumentClass_2 = L\u2019argument \u2018{0}\u2019 ne peut pas \u00eatre de type \u2018{1}\u2019.
IllegalArgumentClass_3 = L\u2019argument \u2018{0}\u2019 ne peut pas \u00eatre de type \u2018{1}\u2019. Une instance de \u2018{2}\u2019 ou d\u2019un type d\u00e9riv\u00e9 \u00e9tait attendue.
+IllegalArgumentField_4 = L\u2019argument \u2018{0}\u2019 n\u2019accepte pas la valeur \u201c{1}\u201d parce que le champs \u2018{2}\u2019 ne peut pas prendre la valeur \u201c{3}\u201d.
IllegalArgumentValue_2 = L\u2019argument \u2018{0}\u2019 n\u2019accepte pas la valeur \u201c{1}\u201d.
IllegalBitsPattern_1 = Pattern de bits invalide: {0}.
IllegalClass_2 = La classe \u2018{0}\u2019 est ill\u00e9gale. Il doit s\u2019agir d\u2019une classe \u2018{1}\u2019 ou d\u00e9riv\u00e9e.
@@ -41,6 +41,10 @@ NodeChildOfItself_1 = Le n\u
NodeHasAnotherParent_1 = Le n\u0153ud \u201c{0}\u201d a d\u00e9j\u00e0 un autre parent.
NodeHasNoParent_1 = Le n\u0153ud \u201c{0}\u201d n\u2019a pas de parent.
NodeNotFound_1 = Aucun n\u0153ud \u201c{0}\u201d n\u2019a \u00e9t\u00e9 trouv\u00e9.
+NonAngularUnit_1 = \u201c{0}\u201d n\u2019est pas une unit\u00e9 d\u2019angles.
+NonLinearUnit_1 = \u201c{0}\u201d n\u2019est pas une unit\u00e9 de longueurs.
+NonScaleUnit_1 = \u201c{0}\u201d n\u2019est pas une unit\u00e9 d\u2019\u00e9chelles.
+NonTemporalUnit_1 = \u201c{0}\u201d n\u2019est pas une unit\u00e9 de temps.
NotANumber_1 = L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre NaN (Not-a-Number).
NotAPrimitiveWrapper_1 = La classe \u2018{0}\u2019 n\u2019est pas un adaptateur d\u2019un type primitif.
NullArgument_1 = L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre nul.
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java Sat Dec 1 09:12:21 2012
@@ -54,6 +54,16 @@ public final class Vocabulary extends In
}
/**
+ * Angle
+ */
+ public static final int Angle = 9;
+
+ /**
+ * Degrees
+ */
+ public static final int Degrees = 10;
+
+ /**
* Maximum value
*/
public static final int MaximumValue = 5;
@@ -69,6 +79,11 @@ public final class Vocabulary extends In
public static final int MinimumValue = 4;
/**
+ * Minutes
+ */
+ public static final int Minutes = 11;
+
+ /**
* Name
*/
public static final int Name = 0;
@@ -89,6 +104,11 @@ public final class Vocabulary extends In
public static final int RootMeanSquare = 7;
/**
+ * Seconds
+ */
+ public static final int Seconds = 12;
+
+ /**
* Standard deviation
*/
public static final int StandardDeviation = 8;
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties Sat Dec 1 09:12:21 2012
@@ -14,12 +14,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+Angle = Angle
+Degrees = Degrees
MaximumValue = Maximum value
MeanValue = Mean value
MinimumValue = Minimum value
+Minutes = Minutes
Name = Name
NumberOfValues = Number of values
NumberOfNaN = Number of \u2018NaN\u2019
RootMeanSquare = Root Mean Square
StandardDeviation = Standard deviation
+Seconds = Seconds
Type = Type
Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties Sat Dec 1 09:12:21 2012
@@ -14,12 +14,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+Angle = Angle
+Degrees = Degr\u00e9s
MaximumValue = Valeur maximale
MeanValue = Valeur moyenne
MinimumValue = Valeur minimale
+Minutes = Minutes
Name = Nom
NumberOfValues = Nombre de valeurs
NumberOfNaN = Nombre de \u2018NaN\u2019
RootMeanSquare = Moyenne quadratique
+Seconds = Secondes
StandardDeviation = \u00c9cart type
Type = Type
Added: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/UnitsTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/UnitsTest.java?rev=1415953&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/UnitsTest.java (added)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/UnitsTest.java Sat Dec 1 09:12:21 2012
@@ -0,0 +1,273 @@
+/*
+ * 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.measure;
+
+import javax.measure.unit.Unit;
+import javax.measure.quantity.Quantity;
+import javax.measure.converter.UnitConverter;
+import org.apache.sis.test.TestCase;
+import org.junit.*;
+
+import static javax.measure.unit.Unit.ONE;
+import static javax.measure.unit.SI.CELSIUS;
+import static javax.measure.unit.SI.METRE;
+import static javax.measure.unit.SI.KILOMETRE;
+import static javax.measure.unit.SI.RADIAN;
+import static javax.measure.unit.NonSI.CENTIRADIAN;
+import static javax.measure.unit.NonSI.DEGREE_ANGLE;
+import static javax.measure.unit.NonSI.MINUTE_ANGLE;
+import static javax.measure.unit.NonSI.SECOND_ANGLE;
+import static javax.measure.unit.NonSI.GRADE;
+import static javax.measure.unit.NonSI.DAY;
+import static javax.measure.unit.NonSI.SPHERE;
+import static javax.measure.unit.NonSI.ATMOSPHERE;
+import static javax.measure.unit.NonSI.NAUTICAL_MILE;
+import static org.apache.sis.measure.Units.*;
+import static org.apache.sis.test.Assert.*;
+
+
+/**
+ * Test conversions using the units declared in {@link Units}.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.3 (derived from geotk-2.5)
+ * @version 0.3
+ * @module
+ */
+public final strictfp class UnitsTest extends TestCase {
+ /**
+ * Compares two values for equality.
+ */
+ private static <Q extends Quantity> void checkConversion(
+ final double expected, final Unit<Q> unitExpected,
+ final double actual, final Unit<Q> unitActual)
+ {
+ UnitConverter converter = unitActual.getConverterTo(unitExpected);
+ assertEquals(expected, converter.convert(actual), 1E-6);
+ converter = converter.inverse();
+ assertEquals(actual, converter.convert(expected), 1E-6);
+ }
+
+ /**
+ * Checks the conversions using {@link Units#SEXAGESIMAL_DMS}.
+ */
+ @Test
+ public void testSexagesimal() {
+ checkConversion(10.00, DEGREE_ANGLE, 10.0000, SEXAGESIMAL_DMS);
+ checkConversion(10.01, DEGREE_ANGLE, 10.0036, SEXAGESIMAL_DMS);
+ checkConversion(10.50, DEGREE_ANGLE, 10.3000, SEXAGESIMAL_DMS);
+ checkConversion(10.99, DEGREE_ANGLE, 10.5924, SEXAGESIMAL_DMS);
+ }
+
+ /**
+ * Tests serialization of units.
+ *
+ * @todo The {@code assertEquals} in this method should actually be {@code assertSame},
+ * but JSR-275 0.9.3 does not resolve units on deserialization.
+ */
+ @Test
+ public void testSerialization() {
+ assertEquals(DEGREE_ANGLE, assertSerializedEquals(DEGREE_ANGLE));
+ assertEquals(SEXAGESIMAL_DMS, assertSerializedEquals(SEXAGESIMAL_DMS));
+ assertEquals(DEGREE_MINUTE_SECOND, assertSerializedEquals(DEGREE_MINUTE_SECOND));
+ assertEquals(PPM, assertSerializedEquals(PPM));
+ }
+
+ /**
+ * Tests {@link Units#isTemporal(Unit)}.
+ */
+ @Test
+ public void testIsTemporal() {
+ // Standard units
+ assertFalse(isTemporal(null));
+ assertFalse(isTemporal(ONE));
+ assertFalse(isTemporal(METRE));
+ assertFalse(isTemporal(RADIAN));
+ assertFalse(isTemporal(CENTIRADIAN));
+ assertFalse(isTemporal(DEGREE_ANGLE));
+ assertFalse(isTemporal(MINUTE_ANGLE));
+ assertFalse(isTemporal(SECOND_ANGLE));
+ assertFalse(isTemporal(GRADE));
+ assertTrue (isTemporal(DAY));
+ assertFalse(isTemporal(SPHERE));
+ assertFalse(isTemporal(ATMOSPHERE));
+ assertFalse(isTemporal(NAUTICAL_MILE));
+
+ // Additional units
+ assertFalse(isTemporal(PPM));
+ assertTrue (isTemporal(MILLISECOND));
+ assertFalse(isTemporal(SEXAGESIMAL_DMS));
+ assertFalse(isTemporal(DEGREE_MINUTE_SECOND));
+ }
+
+ /**
+ * Tests {@link Units#isLinear(Unit)}.
+ */
+ @Test
+ public void testIsLinear() {
+ // Standard units
+ assertFalse(isLinear(null));
+ assertFalse(isLinear(ONE));
+ assertTrue (isLinear(METRE));
+ assertFalse(isLinear(RADIAN));
+ assertFalse(isLinear(CENTIRADIAN));
+ assertFalse(isLinear(DEGREE_ANGLE));
+ assertFalse(isLinear(MINUTE_ANGLE));
+ assertFalse(isLinear(SECOND_ANGLE));
+ assertFalse(isLinear(GRADE));
+ assertFalse(isLinear(DAY));
+ assertFalse(isLinear(SPHERE));
+ assertFalse(isLinear(ATMOSPHERE));
+ assertTrue (isLinear(NAUTICAL_MILE));
+
+ // Additional units
+ assertFalse(isLinear(PPM));
+ assertFalse(isLinear(MILLISECOND));
+ assertFalse(isLinear(SEXAGESIMAL_DMS));
+ assertFalse(isLinear(DEGREE_MINUTE_SECOND));
+ }
+
+ /**
+ * Tests {@link Units#isAngular(Unit)}.
+ */
+ @Test
+ public void testIsAngular() {
+ // Standard units
+ assertFalse(isAngular(null));
+ assertFalse(isAngular(ONE));
+ assertFalse(isAngular(METRE));
+ assertTrue (isAngular(RADIAN));
+ assertTrue (isAngular(CENTIRADIAN));
+ assertTrue (isAngular(DEGREE_ANGLE));
+ assertTrue (isAngular(MINUTE_ANGLE));
+ assertTrue (isAngular(SECOND_ANGLE));
+ assertTrue (isAngular(GRADE));
+ assertFalse(isAngular(DAY));
+ assertFalse(isAngular(SPHERE));
+ assertFalse(isAngular(ATMOSPHERE));
+ assertFalse(isAngular(NAUTICAL_MILE));
+
+ // Additional units
+ assertFalse(isAngular(PPM));
+ assertFalse(isAngular(MILLISECOND));
+ assertTrue (isAngular(SEXAGESIMAL_DMS));
+ assertTrue (isAngular(DEGREE_MINUTE_SECOND));
+ }
+
+ /**
+ * Tests {@link Units#isScale(Unit)}.
+ */
+ @Test
+ public void testIsScale() {
+ // Standard units
+ assertFalse(isScale(null));
+ assertTrue (isScale(ONE));
+ assertFalse(isScale(METRE));
+ assertFalse(isScale(RADIAN));
+ assertFalse(isScale(CENTIRADIAN));
+ assertFalse(isScale(DEGREE_ANGLE));
+ assertFalse(isScale(MINUTE_ANGLE));
+ assertFalse(isScale(SECOND_ANGLE));
+ assertFalse(isScale(GRADE));
+ assertFalse(isScale(DAY));
+ assertFalse(isScale(SPHERE));
+ assertFalse(isScale(ATMOSPHERE));
+ assertFalse(isScale(NAUTICAL_MILE));
+
+ // Additional units
+ assertTrue (isScale(PPM));
+ assertFalse(isScale(MILLISECOND));
+ assertFalse(isScale(SEXAGESIMAL_DMS));
+ assertFalse(isScale(DEGREE_MINUTE_SECOND));
+ }
+
+ /**
+ * Tests {@link Units#isPressure(Unit)}.
+ */
+ @Test
+ public void testIsPressure() {
+ assertFalse(isPressure(null));
+ assertFalse(isPressure(METRE));
+ assertTrue (isPressure(ATMOSPHERE));
+ }
+
+ /**
+ * Tests {@link Units#toStandardUnit(Unit)}.
+ */
+ @Test
+ public void testToStandardUnit() {
+ assertEquals(1000.0, toStandardUnit(KILOMETRE), 1E-15);
+ assertEquals(0.017453292519943295, toStandardUnit(DEGREE_ANGLE), 1E-15);
+ }
+
+ /**
+ * Tests {@link Units#multiply(Unit, double)}.
+ */
+ @Test
+ public void testMultiply() {
+ assertSame(KILOMETRE, multiply(METRE, 1000));
+ assertSame(DEGREE_ANGLE, multiply(RADIAN, 0.017453292519943295));
+ }
+
+ /**
+ * Tests {@link Units#valueOf(String)}.
+ */
+ @Test
+ public void testValueOf() {
+ assertSame(DEGREE_ANGLE, valueOf("°"));
+ assertSame(DEGREE_ANGLE, valueOf("deg"));
+ assertSame(DEGREE_ANGLE, valueOf("degree"));
+ assertSame(DEGREE_ANGLE, valueOf("degrees"));
+ assertSame(DEGREE_ANGLE, valueOf("degrées"));
+ assertSame(DEGREE_ANGLE, valueOf("DEGREES"));
+ assertSame(DEGREE_ANGLE, valueOf("DEGRÃES"));
+ assertSame(DEGREE_ANGLE, valueOf("degrees_east"));
+ assertSame(DEGREE_ANGLE, valueOf("degrées_north"));
+ assertSame(DEGREE_ANGLE, valueOf("decimal_degree"));
+ assertSame(RADIAN, valueOf("rad"));
+ assertSame(RADIAN, valueOf("radian"));
+ assertSame(RADIAN, valueOf("radians"));
+ assertSame(METRE, valueOf("m"));
+ assertSame(METRE, valueOf("metre"));
+ assertSame(METRE, valueOf("meter"));
+ assertSame(METRE, valueOf("metres"));
+ assertSame(METRE, valueOf("mètres"));
+ assertSame(METRE, valueOf("meters"));
+ assertSame(KILOMETRE, valueOf("km"));
+ assertSame(KILOMETRE, valueOf("kilometre"));
+ assertSame(KILOMETRE, valueOf("kilometer"));
+ assertSame(KILOMETRE, valueOf("kilometres"));
+ assertSame(KILOMETRE, valueOf("kilomètres"));
+ assertSame(KILOMETRE, valueOf("kilometers"));
+ assertSame(CELSIUS, valueOf("Celsius"));
+ assertSame(CELSIUS, valueOf("degree Celsius"));
+ assertSame(CELSIUS, valueOf("degree_Celcius"));
+ }
+
+ /**
+ * Tests {@link Units#valueOfEPSG(int)}.
+ *
+ * @since 3.20
+ */
+ @Test
+ public void testValueOfEPSG() {
+ assertSame(METRE, valueOfEPSG(9001));
+ assertSame(DEGREE_ANGLE, valueOfEPSG(9102));
+ assertSame(METRE, valueOf("EPSG:9001"));
+ assertSame(DEGREE_ANGLE, valueOf(" epsg : 9102"));
+ }
+}
Propchange: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/UnitsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/measure/UnitsTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1415953&r1=1415952&r2=1415953&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java (original)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java Sat Dec 1 09:12:21 2012
@@ -59,9 +59,10 @@ import org.junit.runners.Suite;
org.apache.sis.util.type.TypesTest.class,
org.apache.sis.util.type.SimpleInternationalStringTest.class,
org.apache.sis.util.type.DefaultInternationalStringTest.class,
-
- // Formatting
org.apache.sis.internal.util.LocalizedParseExceptionTest.class,
+
+ // Measurements and formatting.
+ org.apache.sis.measure.UnitsTest.class,
org.apache.sis.measure.FormattedCharacterIteratorTest.class,
org.apache.sis.measure.AngleFormatTest.class,
org.apache.sis.measure.AngleTest.class,