sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1767577 [12/15] - in /sis/trunk: ./ application/ application/sis-console/src/main/java/org/apache/sis/console/ application/sis-openoffice/ application/sis-openoffice/src/main/java/org/apache/sis/openoffice/ core/ core/sis-feature/src/main/...
Date Tue, 01 Nov 2016 21:03:08 GMT
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/RangeFormat.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/RangeFormat.java?rev=1767577&r1=1767576&r2=1767577&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/RangeFormat.java [UTF-8]
(original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/RangeFormat.java [UTF-8]
Tue Nov  1 21:03:06 2016
@@ -31,8 +31,7 @@ import java.text.AttributedCharacterIter
 import java.text.FieldPosition;
 import java.text.ParseException;
 import java.text.ParsePosition;
-import javax.measure.unit.Unit;
-import javax.measure.unit.UnitFormat;
+import javax.measure.Unit;
 import org.apache.sis.util.Numbers;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.UnconvertibleObjectException;
@@ -91,7 +90,7 @@ import org.apache.sis.util.resources.Err
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.8
  * @module
  *
  * @see Range#toString()
@@ -309,7 +308,7 @@ public class RangeFormat extends Format
      * Creates a new format for parsing and formatting {@linkplain NumberRange number ranges}
      * using the given locale.
      *
-     * @param  locale The locale for parsing and formatting range components.
+     * @param  locale  the locale for parsing and formatting range components.
      */
     public RangeFormat(final Locale locale) {
         this(locale, Number.class);
@@ -319,8 +318,8 @@ public class RangeFormat extends Format
      * Creates a new format for parsing and formatting {@code Range<Date>}
      * using the given locale and timezone.
      *
-     * @param locale   The locale for parsing and formatting range components.
-     * @param timezone The timezone for the date to be formatted.
+     * @param locale    the locale for parsing and formatting range components.
+     * @param timezone  the timezone for the date to be formatted.
      */
     public RangeFormat(final Locale locale, final TimeZone timezone) {
         this(locale, Date.class);
@@ -332,9 +331,9 @@ public class RangeFormat extends Format
      * the given element type using the given locale. The element type is typically
      * {@code Date.class} or some subclass of {@code Number.class}.
      *
-     * @param  locale The locale for parsing and formatting range components.
-     * @param  elementType The type of range components.
-     * @throws IllegalArgumentException If the given type is not recognized by this constructor.
+     * @param  locale       the locale for parsing and formatting range components.
+     * @param  elementType  the type of range components.
+     * @throws IllegalArgumentException if the given type is not recognized by this constructor.
      */
     public RangeFormat(final Locale locale, final Class<?> elementType) throws IllegalArgumentException
{
         this.elementType = elementType;
@@ -343,7 +342,7 @@ public class RangeFormat extends Format
             unitFormat    = null;
         } else if (Number.class.isAssignableFrom(elementType)) {
             elementFormat = NumberFormat.getNumberInstance(locale);
-            unitFormat    = UnitFormat.getInstance(locale);
+            unitFormat    = new UnitFormat(locale);
         } else if (Date.class.isAssignableFrom(elementType)) {
             elementFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT,
locale);
             unitFormat    = null;
@@ -359,8 +358,8 @@ public class RangeFormat extends Format
         minusSign         = ds.getMinusSign();
         infinity          = ds.getInfinity();
         openSet           = '{';
-        openInclusive     = '['; // Future SIS version may determine those characters from
the locale.
-        openExclusive     = '('; // We may also provide an 'applyPattern(String)' method
for setting those char.
+        openInclusive     = '[';        // Future SIS version may determine those characters
from the locale.
+        openExclusive     = '(';        // We may also provide an 'applyPattern(String)'
method for setting those char.
         openExclusiveAlt  = ']';
         closeSet          = '}';
         closeInclusive    = ']';
@@ -387,9 +386,8 @@ public class RangeFormat extends Format
      * Returns the pattern used by {@link #elementFormat} for formatting the minimum and
      * maximum values. If the element format does not use pattern, returns {@code null}.
      *
-     * @param  localized {@code true} for returning the localized pattern, or {@code false}
-     *         for the unlocalized one.
-     * @return The pattern, or {@code null} if the {@link #elementFormat} doesn't use pattern.
+     * @param  localized {@code true} for returning the localized pattern, or {@code false}
for the unlocalized one.
+     * @return the pattern, or {@code null} if the {@link #elementFormat} doesn't use pattern.
      *
      * @see DecimalFormat#toPattern()
      * @see SimpleDateFormat#toPattern()
@@ -415,9 +413,9 @@ public class RangeFormat extends Format
      * Sets the pattern to be used by {@link #elementFormat} for formatting the minimum and
      * maximum values.
      *
-     * @param  pattern The new pattern.
-     * @param  localized {@code true} if the given pattern is localized.
-     * @throws IllegalStateException If the {@link #elementFormat} does not use pattern.
+     * @param  pattern    the new pattern.
+     * @param  localized  {@code true} if the given pattern is localized.
+     * @throws IllegalStateException if the {@link #elementFormat} does not use pattern.
      *
      * @see DecimalFormat#applyPattern(String)
      * @see SimpleDateFormat#applyPattern(String)
@@ -462,8 +460,7 @@ public class RangeFormat extends Format
     /**
      * Sets whether this {@code RangeFormat} shall use the alternate form at formatting time.
      *
-     * @param alternateForm {@code true} for using the alternate format, or {@code false}
for
-     *        using the default format.
+     * @param alternateForm {@code true} for using the alternate format, or {@code false}
for using the default format.
      */
     public void setAlternateForm(final boolean alternateForm) {
         this.alternateForm = alternateForm;
@@ -521,11 +518,11 @@ public class RangeFormat extends Format
      * Formats a {@link Range} and appends the resulting text to a given string buffer.
      * See the <a href="#skip-navbar_top">class javadoc</a> for a description
of the format.
      *
-     * @param  range      The {@link Range} object to format.
-     * @param  toAppendTo Where the text is to be appended.
-     * @param  pos        Identifies a field in the formatted text, or {@code null} if none.
-     * @return The string buffer passed in as {@code toAppendTo}, with formatted text appended.
-     * @throws IllegalArgumentException If this formatter can not format the given object.
+     * @param  range       the {@link Range} object to format.
+     * @param  toAppendTo  where the text is to be appended.
+     * @param  pos         identifies a field in the formatted text, or {@code null} if none.
+     * @return the string buffer passed in as {@code toAppendTo}, with formatted text appended.
+     * @throws IllegalArgumentException if this formatter can not format the given object.
      */
     @Override
     public StringBuffer format(final Object range, final StringBuffer toAppendTo, final FieldPosition
pos) {
@@ -536,16 +533,14 @@ public class RangeFormat extends Format
     /**
      * Implementation of the format methods.
      *
-     * @param range      The range to format.
-     * @param toAppendTo Where the text is to be appended.
-     * @param pos        Identifies a field in the formatted text, or {@code null} if none.
-     * @param characterIterator The character iterator for which the attributes need to be
set,
-     *        or null if none. This is actually an instance of {@link FormattedCharacterIterator},
-     *        but we use the interface here for avoiding too early class loading.
+     * @param  range              the range to format.
+     * @param  toAppendTo         where the text is to be appended.
+     * @param  pos                identifies a field in the formatted text, or {@code null}
if none.
+     * @param  characterIterator  the character iterator for which the attributes need to
be set, or null if none.
      */
     @SuppressWarnings("fallthrough")
     private void format(final Range<?> range, final StringBuffer toAppendTo, final
FieldPosition pos,
-            final AttributedCharacterIterator characterIterator)
+            final FormattedCharacterIterator characterIterator)
     {
         /*
          * Special case for an empty range. This is typically formatted as "{}". The field
@@ -556,8 +551,8 @@ public class RangeFormat extends Format
             toAppendTo.appendCodePoint(openSet);
             if (fieldPos >= MIN_VALUE_FIELD && fieldPos <= UNIT_FIELD) {
                 final int p = toAppendTo.length();
-                pos.setBeginIndex(p); // First index, inclusive.
-                pos.setEndIndex  (p); // Last index, exclusive
+                pos.setBeginIndex(p);                                   // First index, inclusive.
+                pos.setEndIndex  (p);                                   // Last index, exclusive
             }
             toAppendTo.appendCodePoint(closeSet);
             return;
@@ -578,7 +573,7 @@ public class RangeFormat extends Format
             }
             field = MAX_VALUE_FIELD;
         }
-        toAppendTo.appendCodePoint( // Select the char for the first condition to be true
below:
+        toAppendTo.appendCodePoint(                     // Select the char for the first
condition to be true below:
                 isSingleton           ? openSet :
                 range.isMinIncluded() ? openInclusive :
                 alternateForm         ? openExclusiveAlt :
@@ -594,7 +589,7 @@ public class RangeFormat extends Format
             int startPosition = toAppendTo.length();
             if (value == null) {
                 switch (field) {
-                    case MIN_VALUE_FIELD: toAppendTo.append(minusSign); // Fall through
+                    case MIN_VALUE_FIELD: toAppendTo.append(minusSign);             // Fall
through
                     case MAX_VALUE_FIELD: toAppendTo.append(infinity); break;
                 }
             } else {
@@ -608,8 +603,7 @@ public class RangeFormat extends Format
                     format = elementFormat;
                 }
                 if (characterIterator != null) {
-                    ((FormattedCharacterIterator) characterIterator)
-                            .append(format.formatToCharacterIterator(value), toAppendTo);
+                    characterIterator.append(format.formatToCharacterIterator(value), toAppendTo);
                 } else {
                     format.format(value, toAppendTo, new FieldPosition(-1));
                 }
@@ -619,8 +613,7 @@ public class RangeFormat extends Format
              * then append the separator between this field and the next one.
              */
             if (characterIterator != null) {
-                ((FormattedCharacterIterator) characterIterator)
-                        .addFieldLimit(Field.forCode(field), value, startPosition);
+                characterIterator.addFieldLimit(Field.forCode(field), value, startPosition);
             }
             if (field == fieldPos) {
                 pos.setBeginIndex(startPosition);
@@ -631,7 +624,7 @@ public class RangeFormat extends Format
                     toAppendTo.append(' ').append(separator).append(' ');
                     break;
                 }
-                case MAX_VALUE_FIELD: { // Select the char for the first condition to be
true below:
+                case MAX_VALUE_FIELD: {                 // Select the char for the first
condition to be true below:
                     toAppendTo.appendCodePoint(
                             isSingleton           ? closeSet :
                             range.isMaxIncluded() ? closeInclusive :
@@ -672,8 +665,8 @@ public class RangeFormat extends Format
      * <p>In Apache SIS implementation, the returned character iterator also implements
the
      * {@link CharSequence} interface for convenience.</p>
      *
-     * @param  range {@link Range} object to format.
-     * @return A character iterator together with the attributes describing the formatted
value.
+     * @param  range  the {@link Range} object to format.
+     * @return a character iterator together with the attributes describing the formatted
value.
      * @throws IllegalArgumentException if {@code value} if not an instance of {@link Range}.
      */
     @Override
@@ -688,9 +681,9 @@ public class RangeFormat extends Format
      * Parses text from a string to produce a range. The default implementation delegates
to
      * {@link #parse(String)} with no additional work.
      *
-     * @param  source The text, part of which should be parsed.
-     * @return A range parsed from the string, or {@code null} in case of error.
-     * @throws ParseException If the given string can not be fully parsed.
+     * @param  source  the text, part of which should be parsed.
+     * @return a range parsed from the string.
+     * @throws ParseException if the given string can not be fully parsed.
      */
     @Override
     public Object parseObject(final String source) throws ParseException {
@@ -701,9 +694,9 @@ public class RangeFormat extends Format
      * Parses text from a string to produce a range. The default implementation delegates
to
      * {@link #parse(String, ParsePosition)} with no additional work.
      *
-     * @param  source The text, part of which should be parsed.
-     * @param  pos    Index and error index information as described above.
-     * @return A range parsed from the string, or {@code null} in case of error.
+     * @param  source  the text, part of which should be parsed.
+     * @param  pos     index and error index information as described above.
+     * @return a range parsed from the string, or {@code null} in case of error.
      */
     @Override
     public Object parseObject(final String source, final ParsePosition pos) {
@@ -715,9 +708,9 @@ public class RangeFormat extends Format
      * If there is some unparsed characters after the parsed range, then this method thrown
an
      * exception.
      *
-     * @param  source The text to parse.
-     * @return The parsed range (never {@code null}).
-     * @throws ParseException If the given string can not be fully parsed.
+     * @param  source  the text to parse.
+     * @return the parsed range (never {@code null}).
+     * @throws ParseException if the given string can not be fully parsed.
      */
     public Range<?> parse(final String source) throws ParseException {
         final ParsePosition pos = new ParsePosition(0);
@@ -744,9 +737,9 @@ public class RangeFormat extends Format
      * an error occurs, then the index of {@code pos} is not changed, the error index of
{@code pos}
      * is set to the index of the character where the error occurred, and {@code null} is
returned.
      *
-     * @param  source The text, part of which should be parsed.
-     * @param  pos    Index and error index information as described above.
-     * @return A range parsed from the string, or {@code null} in case of error.
+     * @param  source  the text, part of which should be parsed.
+     * @param  pos     index and error index information as described above.
+     * @return a range parsed from the string, or {@code null} in case of error.
      */
     public Range<?> parse(final String source, final ParsePosition pos) {
         final int origin = pos.getIndex();
@@ -821,7 +814,7 @@ public class RangeFormat extends Format
                 if (value == null) {
                     return null;
                 }
-                pos.setErrorIndex(index); // In case of failure during the conversion.
+                pos.setErrorIndex(index);                   // In case of failure during
the conversion.
                 minValue = maxValue = convert(value);
                 index = pos.getIndex();
                 isMinIncluded = isMaxIncluded = true;
@@ -860,7 +853,7 @@ public class RangeFormat extends Format
                 c = source.codePointAt(index);
             } while (Character.isWhitespace(c));
             if (isClose(c)) {
-                pos.setErrorIndex(index);  // In case of failure during the conversion.
+                pos.setErrorIndex(index);                   // In case of failure during
the conversion.
                 minValue = maxValue = valueOfNil();
                 isMaxIncluded = false;
                 index += Character.charCount(c);
@@ -883,7 +876,7 @@ public class RangeFormat extends Format
                     }
                     pos.setIndex(index += infinity.length());
                 }
-                pos.setErrorIndex(savedIndex); // In case of failure during the conversion.
+                pos.setErrorIndex(savedIndex);              // In case of failure during
the conversion.
                 minValue = convert(value);
                 /*
                  * Parsing of minimal value succeed and its type is valid. Now look for the
@@ -919,7 +912,7 @@ public class RangeFormat extends Format
                         }
                         pos.setIndex(index += infinity.length());
                     }
-                    pos.setErrorIndex(index); // In case of failure during the conversion.
+                    pos.setErrorIndex(index);               // In case of failure during
the conversion.
                     maxValue = convert(value);
                     /*
                      * Skip one last time the whitespaces. The check for the closing bracket
@@ -961,8 +954,7 @@ public class RangeFormat extends Format
                 // At this point we found a character that could be
                 // the beginning of a unit symbol. Try to parse that.
                 pos.setIndex(index);
-// TODO: Uncomment when we have upgrated JSR-275 dependency.
-//              unit = unitFormat.parse(source, pos);
+                unit = unitFormat.parse(source, pos);
                 break;
             }
         }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java?rev=1767577&r1=1767576&r2=1767577&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
[UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
[UTF-8] Tue Nov  1 21:03:06 2016
@@ -16,38 +16,36 @@
  */
 package org.apache.sis.measure;
 
-import java.math.BigDecimal;
-import java.math.MathContext;
-import javax.measure.unit.Unit;
-import javax.measure.unit.NonSI;
+import java.util.List;
+import java.util.Collections;
+import javax.measure.Unit;
 import javax.measure.quantity.Angle;
-import javax.measure.converter.UnitConverter;
+import javax.measure.UnitConverter;
+import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Vocabulary;
-import org.apache.sis.internal.util.PatchedUnitFormat;
 
 import static org.apache.sis.math.MathFunctions.truncate;
 
 
 /**
- * A converter from fractional degrees to sexagesimal degrees. Sexagesimal degrees are pseudo-unit
+ * A converter from decimal 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>
+ * <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>
  *
  * <div class="section">Immutability and thread safety</div>
  * This class and all inner classes are immutable, and thus inherently thread-safe.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
- * @version 0.6
+ * @version 0.8
  * @module
  */
-class SexagesimalConverter extends UnitConverter { // Intentionally not final.
+class SexagesimalConverter extends AbstractConverter {
     /**
      * Serial number for compatibility with different versions.
      */
@@ -70,12 +68,8 @@ class SexagesimalConverter extends UnitC
      * <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 used in the
EPSG
      * database (code 9111).</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> DM = NonSI.DEGREE_ANGLE.transform(
-            new SexagesimalConverter(false, 100).inverse()).asType(Angle.class);//.alternate("D.M");
+    static final ConventionalUnit<Angle> DM;
 
     /**
      * Pseudo-unit for sexagesimal degree. Numbers in this pseudo-unit have the following
format:
@@ -89,12 +83,8 @@ class SexagesimalConverter extends UnitC
      * <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> DMS = NonSI.DEGREE_ANGLE.transform(
-            new SexagesimalConverter(true, 10000).inverse()).asType(Angle.class);//.alternate("D.MS");
+    static final Unit<Angle> DMS;
 
     /**
      * Pseudo-unit for degree - minute - second.
@@ -109,18 +99,19 @@ class SexagesimalConverter extends UnitC
      * <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> DMS_SCALED = NonSI.DEGREE_ANGLE.transform(
-            new SexagesimalConverter(true, 1).inverse()).asType(Angle.class);//.alternate("DMS");
-
-    /*
-     * Declares the units that we were not able to declare in calls to Unit.alternate(String).
      */
+    static final Unit<Angle> DMS_SCALED;
     static {
-        PatchedUnitFormat.init(DM, "D.M", DMS, "D.MS", DMS_SCALED, "DMS");
+        final SystemUnit<Angle> rad = (SystemUnit<Angle>) Units.RADIAN;
+        final UnitConverter toRadian = Units.DEGREE.getConverterTo(rad);
+        DM = new ConventionalUnit<>(rad, new ConcatenatedConverter(
+                new SexagesimalConverter(false, 100).inverse(), toRadian), "D.M", UnitRegistry.OTHER,
(short) 9111);
+
+        DMS = new ConventionalUnit<>(rad, new ConcatenatedConverter(
+                new SexagesimalConverter(true, 10000).inverse(), toRadian), "D.MS", UnitRegistry.OTHER,
(short) 9110);
+
+        DMS_SCALED = new ConventionalUnit<>(rad, new ConcatenatedConverter(
+                new SexagesimalConverter(true, 1).inverse(), toRadian), "DMS", UnitRegistry.OTHER,
(short) 9107);
     }
 
     /**
@@ -143,8 +134,8 @@ class SexagesimalConverter extends UnitC
     /**
      * Constructs a converter for sexagesimal units.
      *
-     * @param hasSeconds {@code true} if the seconds field is present.
-     * @param divider The value to divide DMS unit by.
+     * @param hasSeconds  {@code true} if the seconds field is present.
+     * @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.
      */
@@ -165,6 +156,31 @@ class SexagesimalConverter extends UnitC
     }
 
     /**
+     * Returns {@code false} since this converter is not an identity function.
+     */
+    @Override
+    public boolean isIdentity() {
+        return false;
+    }
+
+    /**
+     * Returns {@code false} since the conversion is non-linear.
+     */
+    @Override
+    public boolean isLinear() {
+        return false;
+    }
+
+    /**
+     * Returns a collection containing only {@code this} since this conversion is not
+     * a concatenation of other converters.
+     */
+    @Override
+    public List<? extends UnitConverter> getConversionSteps() {
+        return Collections.singletonList(this);
+    }
+
+    /**
      * Returns the inverse of this converter.
      */
     @Override
@@ -181,7 +197,7 @@ class SexagesimalConverter extends UnitC
         angle = (angle - deg) * 60;
         if (hasSeconds) {
             final double min = truncate(angle);
-            angle  = (angle - min) * 60; // Secondes
+            angle  = (angle - min) * 60;                // Secondes
             angle += (deg*100 + min)*100;
         } else {
             angle += deg * 100;
@@ -192,11 +208,34 @@ class SexagesimalConverter extends UnitC
     /**
      * 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.
+     * so it may not provide the accuracy normally required by this method contract.
+     */
+    @Override
+    public final Number convert(final Number value) {
+        return convert(value.doubleValue());
+    }
+
+    /**
+     * Considers this converter as non-derivable. Actually it would be possible to provide
a derivative value
+     * for input values other than the discontinuities points, but for now we presume that
it is less dangerous
+     * to return NaN every time, so the user can not miss that this function is not derivable
everywhere.
+     */
+    @Override
+    public final double derivative(double value) {
+        return Double.NaN;
+    }
+
+    /**
+     * Concatenates this converter with another converter. The resulting converter is equivalent
to first converting
+     * by the specified converter (right converter), and then converting by this converter
(left converter).
      */
     @Override
-    public final BigDecimal convert(final BigDecimal value, final MathContext context) {
-        return new BigDecimal(convert(value.doubleValue()), context);
+    public UnitConverter concatenate(final UnitConverter converter) {
+        ArgumentChecks.ensureNonNull("converter", converter);
+        if (equals(converter.inverse())) {
+            return LinearConverter.IDENTITY;
+        }
+        return new ConcatenatedConverter(converter, this);
     }
 
     /**
@@ -217,7 +256,7 @@ class SexagesimalConverter extends UnitC
     }
 
     /**
-     * The inverse of {@link SexagesimalConverter}.
+     * The inverse of {@link SexagesimalConverter}, i.e. the converter from sexagesimal degrees
to decimal degrees.
      */
     private static final class Inverse extends SexagesimalConverter {
         /**
@@ -250,7 +289,7 @@ class SexagesimalConverter extends UnitC
                 deg = truncate(min / 100);
                 min -= deg * 100;
             }
-            if (min <= -60 || min >= 60) {  // Do not enter for NaN
+            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;
@@ -258,7 +297,7 @@ class SexagesimalConverter extends UnitC
                     throw illegalField(angle, min, Vocabulary.Keys.AngularMinutes);
                 }
             }
-            if (sec <= -60 || sec >= 60) { // Do not enter for NaN
+            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;
@@ -272,10 +311,10 @@ class SexagesimalConverter extends UnitC
         /**
          * 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.
+         * @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 short unit) {
             return new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentField_4,



Mime
View raw message