sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1762647 [2/10] - in /sis/trunk: ./ application/sis-webapp/src/test/ core/sis-feature/src/main/java/org/apache/sis/feature/ core/sis-metadata/src/main/java/org/apache/sis/metadata/ core/sis-metadata/src/main/java/org/apache/sis/metadata/iso...
Date Wed, 28 Sep 2016 13:01:40 GMT
Modified: sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultResolution.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultResolution.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultResolution.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultResolution.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -121,7 +121,7 @@ public class DefaultResolution extends I
     /**
      * Creates a new resolution initialized to the given scale.
      *
-     * @param scale The scale, or {@code null} if none.
+     * @param  scale  the scale, or {@code null} if none.
      *
      * @since 0.4
      */
@@ -152,7 +152,7 @@ public class DefaultResolution extends I
      * metadata instances can also be obtained by unmarshalling an invalid XML document.
      * </div>
      *
-     * @param object The metadata to copy values from, or {@code null} if none.
+     * @param  object  the metadata to copy values from, or {@code null} if none.
      *
      * @see #castOrCopy(Resolution)
      */
@@ -192,8 +192,8 @@ public class DefaultResolution extends I
      *       metadata contained in the given object are not recursively copied.</li>
      * </ul>
      *
-     * @param  object The object to get as a SIS implementation, or {@code null} if none.
-     * @return A SIS implementation containing the values of the given object (may be the
+     * @param  object  the object to get as a SIS implementation, or {@code null} if none.
+     * @return a SIS implementation containing the values of the given object (may be the
      *         given object itself), or {@code null} if the argument was null.
      */
     public static DefaultResolution castOrCopy(final Resolution object) {
@@ -207,8 +207,8 @@ public class DefaultResolution extends I
      * Sets the properties identified by the {@code code} argument, if non-null.
      * This discards any other properties.
      *
-     * @param code     The property which is going to be set.
-     * @param newValue The new value.
+     * @param  code      the property which is going to be set.
+     * @param  newValue  the new value.
      */
     private void setProperty(final byte code, final Object newValue) {
         checkWritePermission();
@@ -226,7 +226,7 @@ public class DefaultResolution extends I
     /**
      * Returns the level of detail expressed as the scale of a comparable hardcopy map or chart.
      *
-     * @return Level of detail expressed as the scale of a comparable hardcopy, or {@code null}.
+     * @return level of detail expressed as the scale of a comparable hardcopy, or {@code null}.
      */
     @Override
     @XmlElement(name = "equivalentScale")
@@ -241,7 +241,7 @@ public class DefaultResolution extends I
      * If and only if the {@code newValue} is non-null, then this method automatically
      * discards all other properties.
      *
-     * @param newValue The new equivalent scale.
+     * @param  newValue  the new equivalent scale.
      */
     public void setEquivalentScale(final RepresentativeFraction newValue) {
         setProperty(SCALE, newValue);
@@ -250,7 +250,7 @@ public class DefaultResolution extends I
     /**
      * Returns the ground sample distance.
      *
-     * @return The ground sample distance, or {@code null}.
+     * @return the ground sample distance, or {@code null}.
      */
     @Override
     @XmlElement(name = "distance")
@@ -267,7 +267,7 @@ public class DefaultResolution extends I
      * If and only if the {@code newValue} is non-null, then this method automatically
      * discards all other properties.
      *
-     * @param newValue The new distance, or {@code null}.
+     * @param  newValue  the new distance, or {@code null}.
      * @throws IllegalArgumentException if the given value is NaN, zero or negative.
      */
     public void setDistance(final Double newValue) {
@@ -279,7 +279,7 @@ public class DefaultResolution extends I
     /**
      * Returns the vertical sampling distance.
      *
-     * @return The vertical sampling distance, or {@code null}.
+     * @return the vertical sampling distance, or {@code null}.
      *
      * @since 0.5
      */
@@ -296,7 +296,7 @@ public class DefaultResolution extends I
      * If and only if the {@code newValue} is non-null, then this method automatically
      * discards all other properties.
      *
-     * @param newValue The new distance, or {@code null}.
+     * @param  newValue  the new distance, or {@code null}.
      * @throws IllegalArgumentException if the given value is NaN, zero or negative.
      *
      * @since 0.5
@@ -310,7 +310,7 @@ public class DefaultResolution extends I
     /**
      * Returns the angular sampling measure.
      *
-     * @return The angular sampling measure, or {@code null}.
+     * @return the angular sampling measure, or {@code null}.
      *
      * @since 0.5
      */
@@ -327,7 +327,7 @@ public class DefaultResolution extends I
      * If and only if the {@code newValue} is non-null, then this method automatically
      * discards all other properties.
      *
-     * @param newValue The new distance, or {@code null}.
+     * @param  newValue  the new distance, or {@code null}.
      * @throws IllegalArgumentException if the given value is NaN, zero or negative.
      *
      * @since 0.5
@@ -341,7 +341,7 @@ public class DefaultResolution extends I
     /**
      * Returns a brief textual description of the spatial resolution of the resource.
      *
-     * @return Textual description of the spatial resolution, or {@code null}.
+     * @return textual description of the spatial resolution, or {@code null}.
      *
      * @since 0.5
      */
@@ -357,7 +357,7 @@ public class DefaultResolution extends I
      * If and only if the {@code newValue} is non-null, then this method automatically
      * discards all other properties.
      *
-     * @param newValue The new distance.
+     * @param  newValue  the new distance.
      *
      * @since 0.5
      */

Modified: sis/trunk/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -86,6 +86,7 @@ import static org.apache.sis.metadata.Pr
  * @version 0.5
  * @module
  */
+@SuppressWarnings("OverlyStrongTypeCast")
 @DependsOn(PropertyInformationTest.class)
 public final strictfp class PropertyAccessorTest extends TestCase {
     /**

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -165,7 +165,7 @@ public class GeodeticObjectBuilder exten
      *
      * This method can be invoked only once.
      *
-     * @param  name Name of the conversion method.
+     * @param  name  name of the conversion method.
      * @return {@code this}, for method call chaining.
      * @throws FactoryException if the operation method of the given name can not be obtained.
      */
@@ -182,8 +182,8 @@ public class GeodeticObjectBuilder exten
      * Sets the name of the conversion to use for creating a {@code ProjectedCRS} or {@code DerivedCRS}.
      * This name is for information purpose; its value does not impact the numerical results of coordinate operations.
      *
-     * @param  name The name to give to the conversion.
-     * @return {@code this}, for method call chaining.
+     * @param  name  the name to give to the conversion.
+     * @return {@code this}, for method calls chaining.
      */
     public GeodeticObjectBuilder setConversionName(final String name) {
         conversionName = name;
@@ -203,10 +203,10 @@ public class GeodeticObjectBuilder exten
      * Sets the value of a numeric parameter. The {@link #setConversionMethod(String)} method must have been invoked
      * exactly once before this method. Calls to this {@code setParameter(…)} can be repeated as many times as needed.
      *
-     * @param  name  The parameter name.
-     * @param  value The value to give to the parameter.
-     * @param  unit  Unit of measurement for the given value.
-     * @return {@code this}, for method call chaining.
+     * @param  name   the parameter name.
+     * @param  value  the value to give to the parameter.
+     * @param  unit   unit of measurement for the given value.
+     * @return {@code this}, for method calls chaining.
      * @throws IllegalStateException if {@link #setConversionMethod(String)} has not been invoked before this method.
      * @throws ParameterNotFoundException if there is no parameter of the given name.
      * @throws InvalidParameterValueException if the parameter does not accept the given value.
@@ -240,10 +240,10 @@ public class GeodeticObjectBuilder exten
      *   <tr><td>False northing</td>                 <td>0 (North hemisphere) or 10000000 (South hemisphere) metres</td></tr>
      * </table></blockquote>
      *
-     * @param  isUTM      If {@code true}, the given central meridian will be snapped to the central meridian of a UTM zone.
-     * @param  latitude   The latitude in the center of the desired projection.
-     * @param  longitude  The longitude in the center of the desired projection.
-     * @return {@code this}, for method call chaining.
+     * @param  isUTM      if {@code true}, the given central meridian will be snapped to the central meridian of a UTM zone.
+     * @param  latitude   the latitude in the center of the desired projection.
+     * @param  longitude  the longitude in the center of the desired projection.
+     * @return {@code this}, for method calls chaining.
      * @throws FactoryException if the operation method for the Transverse Mercator projection can not be obtained.
      */
     public GeodeticObjectBuilder setTransverseMercator(boolean isUTM, double latitude, double longitude)
@@ -279,9 +279,9 @@ public class GeodeticObjectBuilder exten
      * }
      * </div>
      *
-     * @param  baseCRS Coordinate reference system to base the derived CRS on.
-     * @param  derivedCS The coordinate system for the derived CRS.
-     * @return The projected CRS.
+     * @param  baseCRS    coordinate reference system to base the derived CRS on.
+     * @param  derivedCS  the coordinate system for the derived CRS.
+     * @return the projected CRS.
      * @throws FactoryException if an error occurred while building the projected CRS.
      */
     public ProjectedCRS createProjectedCRS(final GeographicCRS baseCRS, final CartesianCS derivedCS) throws FactoryException {
@@ -315,9 +315,9 @@ public class GeodeticObjectBuilder exten
      * Creates a temporal CRS from the given origin and temporal unit. For this method, the CRS name is optional:
      * if no {@code addName(…)} method has been invoked, then a default name will be used.
      *
-     * @param  origin The epoch in milliseconds since January 1st, 1970 at midnight UTC.
-     * @param  unit The unit of measurement.
-     * @return A temporal CRS using the given origin and units.
+     * @param  origin  the epoch in milliseconds since January 1st, 1970 at midnight UTC.
+     * @param  unit    the unit of measurement.
+     * @return a temporal CRS using the given origin and units.
      * @throws FactoryException if an error occurred while building the temporal CRS.
      */
     public TemporalCRS createTemporalCRS(final Date origin, final Unit<Duration> unit) throws FactoryException {
@@ -379,8 +379,8 @@ public class GeodeticObjectBuilder exten
      * Creates a compound CRS, but we special processing for (two-dimensional Geographic + ellipsoidal heights) tupples.
      * If any such tupple is found, a three-dimensional geographic CRS is created instead than the compound CRS.
      *
-     * @param  components ordered array of {@code CoordinateReferenceSystem} objects.
-     * @return The coordinate reference system for the given properties.
+     * @param  components  ordered array of {@code CoordinateReferenceSystem} objects.
+     * @return the coordinate reference system for the given properties.
      * @throws FactoryException if the object creation failed.
      */
     public CoordinateReferenceSystem createCompoundCRS(final CoordinateReferenceSystem... components) throws FactoryException {

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -24,11 +24,15 @@ import javax.measure.quantity.Angle;
 import org.opengis.annotation.UML;
 import org.opengis.annotation.Specification;
 import org.opengis.metadata.Identifier;
+import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.referencing.cs.*;
 import org.opengis.referencing.crs.*;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.datum.PrimeMeridian;
+import org.opengis.referencing.operation.CoordinateOperationFactory;
+import org.opengis.util.FactoryException;
+import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.CharSequences;
@@ -37,6 +41,7 @@ import org.apache.sis.referencing.Identi
 import org.apache.sis.referencing.datum.DefaultPrimeMeridian;
 import org.apache.sis.referencing.crs.DefaultGeographicCRS;
 import org.apache.sis.referencing.cs.AxesConvention;
+import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
 import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory.Context;
 
 import static java.util.Collections.singletonMap;
@@ -51,7 +56,7 @@ import static java.util.Collections.sing
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.5
- * @version 0.7
+ * @version 0.8
  * @module
  */
 public final class ReferencingUtilities extends Static {
@@ -370,4 +375,27 @@ public final class ReferencingUtilities
         }
         return context;
     }
+
+    /**
+     * Creates a projected CRS from the given parameters using the default factories.
+     *
+     * @param  properties   the name and other properties, to be given both to the conversion and the CRS.
+     * @param  baseCRS      the base geographic CRS.
+     * @param  parameters   the map projection parameters.
+     * @param  cs           the projected coordinate system.
+     * @return the projected coordinate reference system.
+     * @throws FactoryException if an error occurred while creating the CRS.
+     *
+     * @since 0.8
+     */
+    public static ProjectedCRS createProjectedCRS(final Map<String,String> properties,
+            final GeographicCRS baseCRS, final ParameterValueGroup parameters, final CartesianCS cs)
+            throws FactoryException
+    {
+        final DefaultCoordinateOperationFactory factory = DefaultFactories.forBuildin(
+                CoordinateOperationFactory.class, DefaultCoordinateOperationFactory.class);
+        return DefaultFactories.forBuildin(CRSFactory.class).createProjectedCRS(properties, baseCRS,
+                factory.createDefiningConversion(properties,
+                        factory.getOperationMethod(parameters.getDescriptor().getName().getCode()), parameters), cs);
+    }
 }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/IntegerList.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/IntegerList.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/IntegerList.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/parameter/IntegerList.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -48,7 +48,7 @@ final class IntegerList {
     /**
      * Creates a list of integers backed by the given array.
      *
-     * @param array The integer values as a Java array.
+     * @param array the integer values as a Java array.
      */
     public IntegerList(final Object array) {
         final StringBuilder builder = new StringBuilder();

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/ArrayConverter.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/ArrayConverter.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/ArrayConverter.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/ArrayConverter.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -63,10 +63,10 @@ final class ArrayConverter<S,T> extends
     /**
      * Creates a new converter for the given source and target classes.
      *
-     * @param sourceClass The {@linkplain #getSourceClass() source class}.
-     * @param targetClass The {@linkplain #getTargetClass() target class}.
-     * @param converter   The converter for array elements. The source and target types shall be
-     *                    the array component types of {@code <S>} and {@code <T>}.
+     * @param  sourceClass  the {@linkplain #getSourceClass() source class}.
+     * @param  targetClass  the {@linkplain #getTargetClass() target class}.
+     * @param  converter    the converter for array elements. The source and target types shall be
+     *                      the array component types of {@code <S>} and {@code <T>}.
      */
     ArrayConverter(final Class<S> sourceClass, final Class<T> targetClass, final ObjectConverter<?,?> converter) {
         super(sourceClass, targetClass);

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/Instant.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/Instant.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/Instant.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/Instant.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -85,4 +85,14 @@ public final class Instant extends Tempo
     public Date toDate() {
         return new Date(millis);
     }
+
+    /**
+     * Returns a new instant with the given amount of nanoseconds added.
+     *
+     * @param   n  amount of nanoseconds to add to this instant.
+     * @return  an instant for a point in time after the given amount of nanoseconds.
+     */
+    public Instant plusNanos(final long n) {
+        return (n == 0) ? this : new Instant(JDK8.addExact(millis, n/1000000));
+    }
 }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/JDK8.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -143,10 +143,11 @@ public final class JDK8 {
     }
 
     /**
-     * Returns the sum of the given numbers.
+     * Safe sum of the given numbers.
+     *
      * @param  x  first value to add.
      * @param  y  second value to add.
-     * @return the result.
+     * @return the sum.
      * @throws ArithmeticException if the result overflows.
      *
      * @since 0.8
@@ -158,10 +159,11 @@ public final class JDK8 {
     }
 
     /**
-     * Returns the product of the arguments,
+     * Safe product of the arguments.
+     *
      * @param  x  first value to multiply.
      * @param  y  second value to multiply.
-     * @return the result.
+     * @return the product.
      * @throws ArithmeticException if the result overflows (Note: not implemented in this placeholder).
      *
      * @since 0.8

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/OffsetDateTime.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/OffsetDateTime.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/OffsetDateTime.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/OffsetDateTime.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -52,12 +52,12 @@ public final class OffsetDateTime extend
      * @return the parsed date.
      * @throws DateTimeParseException if the text cannot be parsed.
      */
-    public static OffsetDateTime parse(String text) {
-        text = StandardDateFormat.fix(text, false);
+    public static OffsetDateTime parse(final CharSequence text) {
+        final String modified = StandardDateFormat.dateToISO(text, 0, false);
         final Date date;
         try {
             synchronized (FORMAT) {
-                date = FORMAT.parse(text);
+                date = FORMAT.parse(modified);
             }
         } catch (ParseException e) {
             throw new DateTimeParseException(e.getLocalizedMessage());

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/OffsetTime.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/OffsetTime.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/OffsetTime.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/OffsetTime.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -52,12 +52,12 @@ public final class OffsetTime extends Te
      * @return the parsed date.
      * @throws DateTimeParseException if the text cannot be parsed.
      */
-    public static OffsetTime parse(String text) {
-        text = StandardDateFormat.fix(text, true);
+    public static OffsetTime parse(final CharSequence text) {
+        final String modified = StandardDateFormat.dateToISO(text, 0, true);
         final Date date;
         try {
             synchronized (FORMAT) {
-                date = FORMAT.parse(text);
+                date = FORMAT.parse(modified);
             }
         } catch (ParseException e) {
             throw new DateTimeParseException(e.getLocalizedMessage());

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/Temporal.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/Temporal.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/Temporal.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jdk8/Temporal.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -16,6 +16,8 @@
  */
 package org.apache.sis.internal.jdk8;
 
+import org.apache.sis.internal.util.Numerics;
+
 
 /**
  * Placeholder for the {@link java.time.temporal.Temporal} interface.
@@ -24,7 +26,7 @@ public class Temporal {
     /**
      * Number of milliseconds since January 1st, 1970 midnight UTC.
      */
-    final long millis;
+    public final long millis;
 
     /**
      * For subclasses in this package only.
@@ -32,4 +34,15 @@ public class Temporal {
     Temporal(final long millis) {
         this.millis = millis;
     }
+
+    @Override
+    public int hashCode() {
+        return Numerics.hashCode(millis) ^ getClass().hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        if (other == this) return true;
+        return (other != null) && getClass().equals(other.getClass()) && millis == ((Temporal) other).millis;
+    }
 }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -51,7 +51,7 @@ import org.apache.sis.internal.jdk8.Func
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
- * @version 0.6
+ * @version 0.8
  * @module
  */
 public final class CollectionsExt extends Static {
@@ -68,9 +68,9 @@ public final class CollectionsExt extend
      *
      * <p>This method is null-safe. Note however that the first element may be null.</p>
      *
-     * @param  <T> The type of elements contained in the iterable.
-     * @param  collection The iterable from which to get the first element, or {@code null}.
-     * @return The first element, or {@code null} if the given iterable is null or empty.
+     * @param  <T>         the type of elements contained in the iterable.
+     * @param  collection  the iterable from which to get the first element, or {@code null}.
+     * @return the first element, or {@code null} if the given iterable is null or empty.
      */
     public static <T> T first(final Iterable<T> collection) {
         if (collection != null) {
@@ -83,10 +83,41 @@ public final class CollectionsExt extend
     }
 
     /**
+     * If the given iterable contains exactly one non-null element, returns that element.
+     * Otherwise returns {@code null}.
+     *
+     * @param  <T>         the type of elements contained in the iterable.
+     * @param  collection  the iterable from which to get the singleton element, or {@code null}.
+     * @return the singleton element, or {@code null} if the given iterable is null or does not
+     *         contain exactly one non-null element.
+     *
+     * @since 0.8
+     */
+    public static <T> T singletonOrNull(final Iterable<T> collection) {
+        if (collection != null) {
+            final Iterator<T> it = collection.iterator();
+            if (it != null) {                                       // This check for null is paranoiac.
+                T element = null;
+                while (it.hasNext()) {
+                    final T next = it.next();
+                    if (next != null) {
+                        if (element != null) {
+                            return null;
+                        }
+                        element = next;
+                    }
+                }
+                return element;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Returns a {@linkplain Queue queue} which is always empty and accepts no element.
      *
-     * @param <E> The type of elements in the empty collection.
-     * @return An empty collection.
+     * @param  <E>  the type of elements in the empty collection.
+     * @return an empty collection.
      *
      * @see Collections#emptyList()
      * @see Collections#emptySet()
@@ -117,9 +148,9 @@ public final class CollectionsExt extend
     /**
      * Returns the given value as a singleton if non-null, or returns an empty set otherwise.
      *
-     * @param  <E> The element type.
-     * @param  element The element to returns in a collection if non-null.
-     * @return A collection containing the given element if non-null, or an empty collection otherwise.
+     * @param  <E>      the element type.
+     * @param  element  the element to returns in a collection if non-null.
+     * @return a collection containing the given element if non-null, or an empty collection otherwise.
      */
     public static <E> Set<E> singletonOrEmpty(final E element) {
         return (element != null) ? Collections.singleton(element) : Collections.<E>emptySet();
@@ -129,9 +160,9 @@ public final class CollectionsExt extend
      * Returns a copy of the given array as a non-empty immutable set.
      * If the given array is empty, then this method returns {@code null}.
      *
-     * @param  <T> The type of elements.
-     * @param  elements The elements to copy in a set.
-     * @return An unmodifiable set which contains all the given elements, or {@code null}.
+     * @param  <T>       the type of elements.
+     * @param  elements  the elements to copy in a set.
+     * @return an unmodifiable set which contains all the given elements, or {@code null}.
      *
      * @since 0.6
      */
@@ -146,9 +177,9 @@ public final class CollectionsExt extend
      * This method is generally not recommended, since public API should prefer empty array instead of null.
      * However this method is occasionally useful for managing private fields.
      *
-     * @param  <E> The type of elements in the array.
-     * @param  array The array, or {@code null}.
-     * @return The given array, or {@code null} if the given array was empty.
+     * @param  <E>    the type of elements in the array.
+     * @param  array  the array, or {@code null}.
+     * @return the given array, or {@code null} if the given array was empty.
      */
     public static <E> E[] nonEmpty(final E[] array) {
         return (array != null && array.length == 0) ? null : array;
@@ -161,10 +192,10 @@ public final class CollectionsExt extend
      * with frameworks that may expect or return null (e.g. if we want to exclude completely an empty collection
      * from marshalling with JAXB).
      *
-     * @param  <T> The type of the collection.
-     * @param  <E> The type of elements in the collection.
-     * @param  c   The collection, or {@code null}.
-     * @return The given collection, or {@code null} if the given collection was empty.
+     * @param  <T>  the type of the collection.
+     * @param  <E>  the type of elements in the collection.
+     * @param  c    the collection, or {@code null}.
+     * @return the given collection, or {@code null} if the given collection was empty.
      */
     public static <T extends Collection<E>, E> T nonEmpty(final T c) {
         return (c != null && c.isEmpty()) ? null : c;
@@ -173,9 +204,9 @@ public final class CollectionsExt extend
     /**
      * Returns the given collection, or {@link Collections#EMPTY_SET} if the given collection is null.
      *
-     * @param  <E> The type of elements in the collection.
-     * @param  c The collection, or {@code null}.
-     * @return The given collection, or an empty set if the given collection was null.
+     * @param  <E>  the type of elements in the collection.
+     * @param  c    the collection, or {@code null}.
+     * @return the given collection, or an empty set if the given collection was null.
      */
     public static <E> Collection<E> nonNull(final Collection<E> c) {
         return (c != null) ? c : Collections.<E>emptySet();
@@ -184,9 +215,9 @@ public final class CollectionsExt extend
     /**
      * Returns the given set, or {@link Collections#EMPTY_SET} if the given set is null.
      *
-     * @param  <E> The type of elements in the collection.
-     * @param  c The collection, or {@code null}.
-     * @return The given collection, or an empty set if the given collection was null.
+     * @param  <E>  the type of elements in the collection.
+     * @param  c    the collection, or {@code null}.
+     * @return the given collection, or an empty set if the given collection was null.
      */
     public static <E> Set<E> nonNull(final Set<E> c) {
         return (c != null) ? c : Collections.<E>emptySet();
@@ -212,12 +243,12 @@ public final class CollectionsExt extend
      * constructors of {@code AbstractIdentifiedObject} subclasses receiving a map of properties,
      * and the contract of our constructors do not allow those other types for now.</div>
      *
-     * @param  <E>        The type of elements in the array to be returned.
-     * @param  name       The parameter name, used only for formatting an error message in case of failure.
-     * @param  value      The value to return as an array, or {@code null}.
-     * @param  emptyArray An instance of {@code new E[0]}. This argument can not be null.
-     * @return The given value as an array of {@code <E>}. Never null.
-     * throws  IllegalArgumentException If the given value is not null, an instance of {@code <E>}
+     * @param  <E>         the type of elements in the array to be returned.
+     * @param  name        the parameter name, used only for formatting an error message in case of failure.
+     * @param  value       the value to return as an array, or {@code null}.
+     * @param  emptyArray  an instance of {@code new E[0]}. This argument can not be null.
+     * @return the given value as an array of {@code <E>}. Never null.
+     * throws  IllegalArgumentException if the given value is not null, an instance of {@code <E>}
      *         or an array of {@code <E>}.
      *
      * @since 0.4
@@ -253,10 +284,10 @@ public final class CollectionsExt extend
      * Creates an initially empty set for elements of the given type.
      * This method will creates specialized set for code lists and enumerations.
      *
-     * @param  <E>   The type of elements in the set.
-     * @param  type  The type of elements in the set.
-     * @param  count The expected number of elements to put in the set.
-     * @return A new set for elements of the given type.
+     * @param  <E>    the type of elements in the set.
+     * @param  type   the type of elements in the set.
+     * @param  count  the expected number of elements to put in the set.
+     * @return a new set for elements of the given type.
      */
     @SuppressWarnings({"unchecked","rawtypes"})
     public static <E> Set<E> createSetForType(final Class<E> type, final int count) {
@@ -275,10 +306,10 @@ public final class CollectionsExt extend
      * sense of {@link Object#equals(Object)}, then only the last instance of the duplicated
      * values will be included in the returned set.
      *
-     * @param  <E>         The type of array elements.
-     * @param  excludeNull {@code true} for excluding the {@code null} element from the returned set.
-     * @param  array       The array to copy in a set. May be {@code null} or contain null elements.
-     * @return A set containing the array elements, or {@code null} if the given array was null.
+     * @param  <E>          the type of array elements.
+     * @param  excludeNull  {@code true} for excluding the {@code null} element from the returned set.
+     * @param  array        the array to copy in a set. May be {@code null} or contain null elements.
+     * @return a set containing the array elements, or {@code null} if the given array was null.
      *
      * @see Collections#unmodifiableSet(Set)
      */
@@ -321,9 +352,9 @@ public final class CollectionsExt extend
      * <strong>not</strong> be modified after this method call. In case of doubt, use the
      * standard {@link Collections#unmodifiableSet(Set)} method instead.</p>
      *
-     * @param  <E>  The type of elements in the set.
-     * @param  set  The set to make unmodifiable, or {@code null}.
-     * @return A unmodifiable version of the given set, or {@code null} if the given set was null.
+     * @param  <E>  the type of elements in the set.
+     * @param  set  the set to make unmodifiable, or {@code null}.
+     * @return a unmodifiable version of the given set, or {@code null} if the given set was null.
      */
     public static <E> Set<E> unmodifiableOrCopy(Set<E> set) {
         if (set != null) {
@@ -356,10 +387,10 @@ public final class CollectionsExt extend
      * <strong>not</strong> be modified after this method call. In case of doubt, use the
      * standard {@link Collections#unmodifiableMap(Map)} method instead.</p>
      *
-     * @param  <K>  The type of keys in the map.
-     * @param  <V>  The type of values in the map.
-     * @param  map  The map to make unmodifiable, or {@code null}.
-     * @return A unmodifiable version of the given map, or {@code null} if the given map was null.
+     * @param  <K>  the type of keys in the map.
+     * @param  <V>  the type of values in the map.
+     * @param  map  the map to make unmodifiable, or {@code null}.
+     * @return a unmodifiable version of the given map, or {@code null} if the given map was null.
      */
     public static <K,V> Map<K,V> unmodifiableOrCopy(Map<K,V> map) {
         if (map != null) {
@@ -400,9 +431,9 @@ public final class CollectionsExt extend
      *
      * This method may not preserve the {@link org.apache.sis.util.collection.CheckedContainer} interface.
      *
-     * @param  <E> The type of elements in the collection.
-     * @param  collection The collection to copy, or {@code null}.
-     * @return A copy of the given collection, or {@code null} if the given collection was null.
+     * @param  <E>         the type of elements in the collection.
+     * @param  collection  the collection to copy, or {@code null}.
+     * @return a copy of the given collection, or {@code null} if the given collection was null.
      */
     @SuppressWarnings("unchecked")
     public static <E> Collection<E> modifiableCopy(final Collection<E> collection) {
@@ -457,10 +488,10 @@ public final class CollectionsExt extend
      * <tr><td>{@link Map} other than above</td><td class="sep">{@link LinkedHashMap}</td></tr>
      * </table>
      *
-     * @param  <K> The type of keys in the map.
-     * @param  <V> The type of values in the map.
-     * @param  map The map to copy, or {@code null}.
-     * @return A copy of the given map, or {@code null} if the given map was null.
+     * @param  <K>  the type of keys in the map.
+     * @param  <V>  the type of values in the map.
+     * @param  map  the map to copy, or {@code null}.
+     * @return a copy of the given map, or {@code null} if the given map was null.
      */
     @SuppressWarnings("unchecked")
     public static <K,V> Map<K,V> modifiableCopy(final Map<K,V> map) {
@@ -490,10 +521,10 @@ public final class CollectionsExt extend
      * view. The intend is to avoid one level of indirection for performance and memory reasons.
      * This is okay only if the map is kept in a private field and never escape outside this class.
      *
-     * @param  <K> The type of keys in the map.
-     * @param  <V> The type of values in the map.
-     * @param  map The map to compact, or {@code null}.
-     * @return A potentially compacted map, or {@code null} if the given map was null.
+     * @param  <K>  the type of keys in the map.
+     * @param  <V>  the type of values in the map.
+     * @param  map  the map to compact, or {@code null}.
+     * @return a potentially compacted map, or {@code null} if the given map was null.
      */
     public static <K,V> Map<K,V> compact(final Map<K,V> map) {
         if (map != null) {
@@ -511,9 +542,9 @@ public final class CollectionsExt extend
      * in the given list after this method call. This method makes no guaranteed about whether
      * the returned list is modifiable or not.
      *
-     * @param  <E>  The type of elements in the list.
-     * @param  list The list for which to take a snapshot, or {@code null} if none.
-     * @return A snapshot of the given list, or {@code list} itself if null or unmodifiable.
+     * @param  <E>   the type of elements in the list.
+     * @param  list  the list for which to take a snapshot, or {@code null} if none.
+     * @return a snapshot of the given list, or {@code list} itself if null or unmodifiable.
      */
     @SuppressWarnings("unchecked")
     public static <E> List<E> snapshot(final List<E> list) {
@@ -534,6 +565,7 @@ public final class CollectionsExt extend
      *   <li>If the value is null, then this method returns an {@linkplain Collections#emptyList() empty list}.</li>
      *   <li>If the value is an instance of {@link Collection}, then it is returned unchanged.</li>
      *   <li>If the value is an array of objects, then it is returned {@linkplain Arrays#asList(Object[]) as a list}.</li>
+     *   <li>If the value is an array of primitive type, then it is returned as a list of their wrapper class.</li>
      *   <li>If the value is an instance of {@link Iterable}, {@link Iterator} or {@link Enumeration}, copies the values in a new list.</li>
      *   <li>Otherwise the value is returned as a {@linkplain Collections#singletonList(Object) singleton list}.</li>
      * </ul>
@@ -548,8 +580,8 @@ public final class CollectionsExt extend
      *     List<?> list = toList(toCollection(object));
      * }
      *
-     * @param  value The value to return as a collection, or {@code null}.
-     * @return The value as a collection, or wrapped in a collection (never {@code null}).
+     * @param  value  the value to return as a collection, or {@code null}.
+     * @return the value as a collection, or wrapped in a collection (never {@code null}).
      */
     public static Collection<?> toCollection(final Object value) {
         if (value == null) {
@@ -558,8 +590,29 @@ public final class CollectionsExt extend
         if (value instanceof Collection<?>) {
             return (Collection<?>) value;
         }
-        if (value instanceof Object[]) {
-            return Arrays.asList((Object[]) value);
+        if (value.getClass().isArray()) {
+            if (value instanceof Object[]) {
+                return Arrays.asList((Object[]) value);
+            } else {
+                return new AbstractList<Object>() {
+                    /** Returns the number of elements in the backing array. */
+                    @Override public int size() {
+                        return Array.getLength(value);
+                    }
+
+                    /** Returns the element at the given index. Primitive numbers as returned as instance of their wrapper class. */
+                    @Override public Object get(final int index) {
+                        return Array.get(value, index);
+                    }
+
+                    /** Sets the element at the given index. Primitive numbers shall be given as instance of their wrapper class. */
+                    @Override public Object set(final int index, final Object value) {
+                        final Object old = Array.get(value, index);
+                        Array.set(value, index, value);
+                        return old;
+                    }
+                };
+            }
         }
         if (value instanceof Iterable<?>) {
             final List<Object> list = new ArrayList<>();
@@ -598,9 +651,9 @@ public final class CollectionsExt extend
      *     List<?> list = toList(toCollection(object));
      * }
      *
-     * @param  <T> The type of elements in the given collection.
-     * @param  collection The collection to cast or copy to a list.
-     * @return The given collection as a list, or a copy of the given collection.
+     * @param  <T>         the type of elements in the given collection.
+     * @param  collection  the collection to cast or copy to a list.
+     * @return the given collection as a list, or a copy of the given collection.
      */
     public static <T> List<T> toList(final Collection<T> collection) {
         if (collection instanceof List<?>) {
@@ -614,10 +667,10 @@ public final class CollectionsExt extend
      * argument is not known at compile-time. If the {@code valueClass} is known at compile-time, then callers should
      * use {@link Collection#toArray(T[])} instead.
      *
-     * @param  <T>        The compile-time value of {@code valueClass}.
-     * @param  collection The collection from which to get the elements.
-     * @param  valueClass The runtime type of collection elements.
-     * @return The collection elements as an array, or {@code null} if {@code collection} is null.
+     * @param  <T>         the compile-time value of {@code valueClass}.
+     * @param  collection  the collection from which to get the elements.
+     * @param  valueClass  the runtime type of collection elements.
+     * @return the collection elements as an array, or {@code null} if {@code collection} is null.
      *
      * @since 0.6
      */
@@ -634,12 +687,12 @@ public final class CollectionsExt extend
      * Adds a value in a pseudo multi-values map. The multi-values map is simulated by a map of lists.
      * The map can be initially empty - lists will be created as needed.
      *
-     * @param  <K>   The type of key elements in the map.
-     * @param  <V>   The type of value elements in the lists.
-     * @param  map   The multi-values map where to add an element.
-     * @param  key   The key of the element to add. Can be null if the given map supports null keys.
-     * @param  value The value of the element to add. Can be null.
-     * @return The list where the given value has been added. May be unmodifiable.
+     * @param  <K>    the type of key elements in the map.
+     * @param  <V>    the type of value elements in the lists.
+     * @param  map    the multi-values map where to add an element.
+     * @param  key    the key of the element to add. Can be null if the given map supports null keys.
+     * @param  value  the value of the element to add. Can be null.
+     * @return the list where the given value has been added. May be unmodifiable.
      */
     public static <K,V> List<V> addToMultiValuesMap(final Map<K,List<V>> map, final K key, final V value) {
         final List<V> singleton = Collections.singletonList(value);
@@ -665,12 +718,12 @@ public final class CollectionsExt extend
      * <p>Code searching in the returned map shall ask for the original (non lower-case) name
      * <strong>before</strong> to ask for the lower-cases version of that name.</p>
      *
-     * @param  <E>          The type of elements.
-     * @param  elements     The elements to store in the map, or {@code null} if none.
-     * @param  nameFunction The function for computing a name from an element.
-     * @param  namesLocale  The locale to use for creating the "all lower cases" names.
-     * @return A (<cite>name</cite>, <cite>element</cite>) mapping with lower cases entries where possible.
-     * @throws InvalidParameterCardinalityException If the same name is used for more than one element.
+     * @param  <E>           the type of elements.
+     * @param  elements      the elements to store in the map, or {@code null} if none.
+     * @param  nameFunction  the function for computing a name from an element.
+     * @param  namesLocale   the locale to use for creating the "all lower cases" names.
+     * @return a (<cite>name</cite>, <cite>element</cite>) mapping with lower cases entries where possible.
+     * @throws InvalidParameterCardinalityException if the same name is used for more than one element.
      */
     public static <E> Map<String,E> toCaseInsensitiveNameMap(final Collection<? extends E> elements,
             final Function<E,String> nameFunction, final Locale namesLocale)
@@ -730,9 +783,9 @@ public final class CollectionsExt extend
      * Returns {@code true} if the next elements returned by the given iterators are the same.
      * This method compares using the identity operation ({@code ==}), not {@code equals(Object)}.
      *
-     * @param  it1 The first iterator.
-     * @param  it2 The second iterator.
-     * @return If both iterators return the same objects.
+     * @param  it1  the first iterator.
+     * @param  it2  the second iterator.
+     * @return if both iterators return the same objects.
      */
     public static boolean identityEquals(final Iterator<?> it1, final Iterator<?> it2) {
         while (it1.hasNext()) {

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -199,6 +199,18 @@ public final class Constants extends Sta
     public static final short EPSG_AXIS_DEGREES = 9122;
 
     /**
+     * EPSG code of "WGS 84 / Arctic Polar Stereographic" projection.
+     * Latitude of standard parallel is 71°N. All other parameters are zero.
+     */
+    public static final short EPSG_ARCTIC_POLAR_STEREOGRAPHIC = 3995;
+
+    /**
+     * EPSG code of "WGS 84 / Antarctic Polar Stereographic" projection.
+     * Latitude of standard parallel is 71°S. All other parameters are zero.
+     */
+    public static final short EPSG_ANTARCTIC_POLAR_STEREOGRAPHIC = 3031;
+
+    /**
      * Do not allow instantiation of this class.
      */
     private Constants() {

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -23,6 +23,10 @@ import java.text.FieldPosition;
 import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk8.Temporal;
+import org.apache.sis.internal.jdk8.DateTimeException;
+
 
 /**
  * A date format used for parsing dates in the {@code "yyyy-MM-dd'T'HH:mm:ss.SSSX"} pattern, but in which
@@ -97,6 +101,22 @@ public final class StandardDateFormat ex
     public static final int MILLISECONDS_PER_DAY = 24*60*60*1000;
 
     /**
+     * Converts the given temporal object into a date.
+     * The given temporal object is typically the value parsed by {@link #FORMAT}.
+     *
+     * @param  temporal  the temporal object to convert, or {@code null}.
+     * @return the legacy date for the given temporal object, or {@code null} if the argument was null.
+     * @throws DateTimeException if a value for the field cannot be obtained.
+     * @throws ArithmeticException if the number of milliseconds is too large.
+     */
+    public static Date toDate(final Temporal temporal) {
+        if (temporal == null) {
+            return null;
+        }
+        return new Date(temporal.millis);
+    }
+
+    /**
      * {@code true} if the user has invoked {@link #applyPattern(String)} or {@link #applyLocalizedPattern(String)}.
      */
     private boolean isUserSpecifiedPattern;
@@ -184,152 +204,148 @@ public final class StandardDateFormat ex
         if (isUserSpecifiedPattern) {
             return super.parse(text, position);
         }
-        final Fix fix = Fix.apply(text, position.getIndex(), 0);
-        if (fix == null) {
-            try {
-                super.applyPattern(SHORT_PATTERN);
-                return super.parse(text, position);
-            } finally {
-                super.applyPattern(PATTERN);
-            }
-        }
-        final Date date = super.parse(fix.text, position);
-        position.setIndex     (fix.adjustIndex(position.getIndex()));
-        position.setErrorIndex(fix.adjustIndex(position.getErrorIndex()));
+        final int fromIndex = position.getIndex();
+        final String modified = dateToISO(text, fromIndex, false);
+        position.setIndex(0);
+        final Date date = super.parse(modified, position);
+        position.setIndex     (adjustIndex(text, modified, fromIndex, position.getIndex()));
+        position.setErrorIndex(adjustIndex(text, modified, fromIndex, position.getErrorIndex()));
         return date;
     }
 
     /**
      * Modifies if needed a given input string in order to make it compliant with JDK7 implementation of
-     * {@code SimpleDateFormat}. That implementation expects the exact some number of fraction digits in
+     * {@code SimpleDateFormat}. That implementation expects the exact same number of fraction digits in
      * the second fields than specified by the {@code "ss.SSS"} part of the pattern. This method adds or
-     * removes fraction digits as needed.
+     * removes fraction digits as needed, and adds a {@code "Z"} suffix if the string has no timezone.
+     *
+     * <p>The string returned by this method starts at {@code fromIndex} and stop after an arbitrary amount
+     * of characters (may be more characters than actually needed for parsing the date).</p>
      *
-     * @param  text  the text to adapt.
-     * @param  time  {@code true} if parsing only a time, or {@code false} if parsing a day and a time.
+     * @param  text       the text to adapt.
+     * @param  fromIndex  index in {@code text} where to start the adaptation.
+     * @param  isTime     {@code true} if parsing only a time, or {@code false} if parsing a day and a time.
      * @return the modified input string, with second fraction digits added or removed.
      */
-    public static String fix(final String text, final boolean time) {
-        final Fix fix = Fix.apply(text, 0, time ? 1 : 0);
-        return (fix != null) ? fix.text : text;
-    }
-
-    /**
-     * Implementation of {@link StandardDateFormat#fix(String)} method together with additional information.
-     */
-    static final class Fix {
-        /**
-         * The modified input string, with second fraction digits added or removed.
-         */
-        public final String text;
-
-        /**
-         * Index of the first character added or removed, or {@code input.length()} if none.
-         */
-        private final int lower;
-
-        /**
-         * Number of characters added (positive number) or removed (negative number).
-         */
-        final int change;
-
-        /**
-         * Wraps information about an input string that has been made parsable.
-         */
-        private Fix(final String text, final int lower, final int change) {
-            this.text   = text;
-            this.lower  = lower;
-            this.change = change;
+    @SuppressWarnings("fallthrough")
+    public static String dateToISO(final CharSequence text, int fromIndex, boolean isTime) {
+        if (text == null) {
+            return null;
         }
-
-        /**
-         * Performs various adjustments for making the given text compliant with the format expected by
-         * a {@link SimpleDateFormat} using the {@value #PATTERN} pattern.
-         *
-         * @param  text       the text to adapt.
-         * @param  s          index in {@code text} where to start the parsing.
-         * @param  timeField  0 if parsing starts on days, 1 if starting on hours field,
-         *                    2 if starting on minutes field or 3 if starting on seconds field.
-         * @return information about the input string made parsable,
-         *         or {@code null} if the given text does not contain a time field.
+        final StringBuilder modified = new StringBuilder(30);
+        /*
+         * Copy characters from the given text to the buffer as long as it seems to be part of a date.
+         * We do not perform a strict check, so we may copy more characters than needed; it will be the
+         * DateFormat' job to tell to the caller where the date ends.
          */
-        static Fix apply(final String text, int s, int timeField) {
-            final int length = text.length();
-search:     while (s < length) {
-                char c = text.charAt(s);
-                if (c < '0' || c > '9') {
-                    switch (c) {
-                        default: {
-                            break search;
-                        }
-                        case '-': {
-                            if (timeField != 0) break search;
-                            break;
-                        }
-                        case 'T': {
-                            if (timeField != 0) break search;
-                            timeField = 1;
-                            break;
-                        }
-                        case ':': {
-                            if (timeField == 0 || ++timeField > 3) break search;
-                            break;
-                        }
-                        case '.': {
-                            if (timeField != 3) break search;
-                            /*
-                             * If the user specified too few or too many fraction digits, add or truncate.
-                             * If the number of digits is already the expected ones (which should be rare),
-                             * nevertheless create a new Fix instance for notifying the parse method that
-                             * the text contains a time.
-                             */
-                            final int start = ++s;
-                            while (s < length && (c = text.charAt(s)) >= '0' && c <= '9') s++;
-                            final int change = NUM_FRACTION_DIGITS - (s - start);
-                            if (change == 0) {
-                                return new Fix(text, length, 0);                    // See above comment.
-                            }
-                            final StringBuilder buffer = new StringBuilder(text);
-                            if (change >= 0) {
-                                for (int i = change; --i >= 0;) {
-                                    buffer.insert(s, '0');
-                                }
-                            } else {
-                                final int upper = s;
-                                s = start + NUM_FRACTION_DIGITS;
-                                buffer.delete(s, upper);
+        int numDigits = 0;
+        int missingTimeFields = 2;
+        boolean isFraction = false;
+        boolean isTimeZone = false;
+copy:   while (fromIndex < text.length()) {
+            char c = text.charAt(fromIndex++);
+            if (c >= '0' && c <= '9') {
+                if (++numDigits > NUM_FRACTION_DIGITS && isFraction) {
+                    continue;       // Ignore extraneous fraction digits.
+                }
+            } else {
+                switch (c) {
+                    default: {
+                        break copy;
+                    }
+                    case 'T': {
+                        if (isTime) break copy;
+                        isTime = true;
+                        break;
+                    }
+                    case ':': {
+                        if (!isTime | isFraction) break copy;
+                        missingTimeFields--;
+                        break;
+                    }
+                    case '.': {
+                        if (!isTime | isFraction | isTimeZone) break copy;
+                        isFraction = true;
+                        break;
+                    }
+                    case '-': {
+                        if (!isTime) break;      // Separator between year-month-day: nothing to do.
+                        // Otherwise timezone offset: same work than for the '+' case (fallthrough).
+                    }
+                    case '+':
+                    case 'Z': {
+                        if (!isTime | isTimeZone) break copy;
+                        if (!isFraction) {
+                            while (--missingTimeFields >= 0) {
+                                modified.append(":00");
                             }
-                            return new Fix(buffer.toString(), s, change);
+                            modified.append('.');
+                            numDigits = 0;
+                        }
+                        while (numDigits < NUM_FRACTION_DIGITS) {
+                            modified.append('0');
+                            numDigits++;
                         }
+                        isFraction = false;
+                        isTimeZone = true;
+                        break;
                     }
                 }
-                s++;
-            }
-            /*
-             * If the user did not specified any fraction digits, add them.
-             * (NUM_FRACTION_DIGITS + 1) shall be the length of the inserted string.
-             */
-            final String time;
-            switch (timeField) {
-                default: return null;
-                case 1:  time = ":00:00.000"; break;
-                case 2:  time =    ":00.000"; break;
-                case 3:  time =       ".000"; break;
+                if (numDigits == 1) {
+                    modified.insert(modified.length() - 1, '0');
+                }
+                numDigits = 0;
             }
-            return new Fix(new StringBuilder(text).insert(s, time).toString(), s, time.length());
+            modified.append(c);
         }
-
-        /**
-         * Map an index in the modified string to the index in the original string.
-         *
-         * @param  index  the index in the modified string.
-         * @return the corresponding index in the original string.
+        /*
+         * Check for missing time fields and time zone. For example if the given date is
+         * "2005-09-22T00:00", then this method will completes it as "2005-09-22T00:00:00".
+         * In addition, a 'Z' suffix will be appended if needed.
          */
-        int adjustIndex(int index) {
-            if (index >= lower) {
-                index = Math.max(lower, index - change);
+        if (numDigits == 1) {
+            modified.insert(modified.length() - 1, '0');
+        }
+        if (!isTimeZone) {
+            if (!isTime) {
+                modified.append("T00");
+            }
+            if (!isFraction) {
+                while (--missingTimeFields >= 0) {
+                    modified.append(":00");
+                }
+                modified.append('.');
+                numDigits = 0;
+            }
+            while (numDigits < NUM_FRACTION_DIGITS) {
+                modified.append('0');
+                numDigits++;
             }
+            modified.append('Z');
+        }
+        return modified.toString();
+    }
+
+    /**
+     * Maps an index in the modified string to the index in the original string.
+     *
+     * @param  text      the original text specified by the user.
+     * @param  modified  the modified text that has been parsed.
+     * @param  offset    index of the first {@code text} character copied in {@code modified}.
+     * @param  index     the index in the modified string.
+     * @return the corresponding index in the original text.
+     */
+    static int adjustIndex(final String text, final String modified, int offset, final int index) {
+        if (index < 0) {
             return index;
         }
+        if (!text.isEmpty()) {
+            for (int i=0; i<index; i++) {
+                if (modified.charAt(i) == text.charAt(offset)) {
+                    if (++offset >= text.length()) break;
+                }
+            }
+        }
+        return offset;
     }
 }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Utilities.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -20,6 +20,7 @@ import java.util.Formatter;
 import java.util.FormattableFlags;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.Classes;
+import org.apache.sis.util.Characters;
 import org.apache.sis.util.CharSequences;
 
 
@@ -55,11 +56,11 @@ public final class Utilities extends Sta
      *   <li>Note that {@code '_'} is valid both in {@code xsd:ID} and Unicode identifier.</li>
      * </ul>
      *
-     * @param  appendTo    The buffer where to append the valid characters.
-     * @param  separator   The separator to append before the valid characters, or 0 if none.
-     * @param  text        The text from which to get the valid character to append in the given buffer.
-     * @param  accepted    Additional characters to accept (e.g. {@code "-."}), or an empty string if none.
-     * @param  toLowerCase {@code true} for converting the characters to lower case.
+     * @param  appendTo     the buffer where to append the valid characters.
+     * @param  separator    the separator to append before the valid characters, or 0 if none.
+     * @param  text         the text from which to get the valid character to append in the given buffer.
+     * @param  accepted     additional characters to accept (e.g. {@code "-."}), or an empty string if none.
+     * @param  toLowerCase  {@code true} for converting the characters to lower case.
      * @return {@code true} if at least one character has been added to the buffer.
      */
     public static boolean appendUnicodeIdentifier(final StringBuilder appendTo, final char separator,
@@ -91,13 +92,57 @@ public final class Utilities extends Sta
     }
 
     /**
+     * Returns a string with the same content than the given string, but in upper case and containing only the
+     * filtered characters. If the given string already matches the criterion, then it is returned unchanged
+     * without creation of any temporary object.
+     *
+     * <p>This method is useful before call to an {@code Enum.valueOf(String)} method, for making the search
+     * a little bit more tolerant.</p>
+     *
+     * <p>This method is not in public API because conversion to upper-cases should be locale-dependent.</p>
+     *
+     * @param  text     the text to filter.
+     * @param  filter   the filter to apply.
+     * @return the filtered text.
+     *
+     * @since 0.8
+     */
+    public static String toUpperCase(final String text, final Characters.Filter filter) {
+        final int length = text.length();
+        int c, i = 0;
+        while (true) {
+            if (i >= length) {
+                return text;
+            }
+            c = text.codePointAt(i);
+            if (!filter.contains(c) || Character.toUpperCase(c) != c) {
+                break;
+            }
+            i += Character.charCount(c);
+        }
+        /*
+         * At this point we found that characters starting from index i does not match the criterion.
+         * Copy what we have checked so far in the buffer, then add next characters one-by-one.
+         */
+        final StringBuilder buffer = new StringBuilder(length).append(text, 0, i);
+        while (i < length) {
+            c = text.codePointAt(i);
+            if (filter.contains(c)) {
+                buffer.appendCodePoint(Character.toUpperCase(c));
+            }
+            i += Character.charCount(c);
+        }
+        return buffer.toString();
+    }
+
+    /**
      * Returns a string representation of an instance of the given class having the given properties.
      * This is a convenience method for implementation of {@link Object#toString()} methods that are
      * used mostly for debugging purpose.
      *
-     * @param  classe     The class to format.
-     * @param  properties The (<var>key</var>=<var>value</var>) pairs.
-     * @return A string representation of an instance of the given class having the given properties.
+     * @param  classe      the class to format.
+     * @param  properties  the (<var>key</var>=<var>value</var>) pairs.
+     * @return a string representation of an instance of the given class having the given properties.
      *
      * @since 0.4
      */
@@ -125,11 +170,11 @@ public final class Utilities extends Sta
      * Formats the given character sequence to the given formatter. This method takes in account
      * the {@link FormattableFlags#UPPERCASE} and {@link FormattableFlags#LEFT_JUSTIFY} flags.
      *
-     * @param formatter The formatter in which to format the value.
-     * @param flags     The formatting flags.
-     * @param width     Minimal number of characters to write, padding with {@code ' '} if necessary.
-     * @param precision Number of characters to keep before truncation, or -1 if no limit.
-     * @param value     The text to format.
+     * @param formatter  the formatter in which to format the value.
+     * @param flags      the formatting flags.
+     * @param width      minimal number of characters to write, padding with {@code ' '} if necessary.
+     * @param precision  number of characters to keep before truncation, or -1 if no limit.
+     * @param value      the text to format.
      */
     public static void formatTo(final Formatter formatter, final int flags,
             int width, int precision, String value)
@@ -140,7 +185,7 @@ public final class Utilities extends Sta
         if (isUpperCase && width > 0) {
             // May change the string length in some locales.
             value = value.toUpperCase(formatter.locale());
-            isUpperCase = false; // Because conversion has already been done.
+            isUpperCase = false;                            // Because conversion has already been done.
         }
         int length = value.length();
         if (precision >= 0) {

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java?rev=1762647&r1=1762646&r2=1762647&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java [UTF-8] Wed Sep 28 13:01:39 2016
@@ -112,8 +112,8 @@ public abstract class CompoundFormat<T>
      * {@link Locale#ROOT} if this format shall parse and format "unlocalized" strings.
      * See {@link #getLocale()} for more information about the {@code ROOT} locale.
      *
-     * @param locale   The locale for the new {@code Format}, or {@code null} for {@code Locale.ROOT}.
-     * @param timezone The timezone, or {@code null} for UTC.
+     * @param  locale    the locale for the new {@code Format}, or {@code null} for {@code Locale.ROOT}.
+     * @param  timezone  the timezone, or {@code null} for UTC.
      */
     protected CompoundFormat(final Locale locale, final TimeZone timezone) {
         this.locale   = (locale != null) ? locale : Locale.ROOT;
@@ -130,7 +130,7 @@ public abstract class CompoundFormat<T>
      *   <li>Format {@link Date} instances using the ISO pattern instead than the English one.</li>
      * </ul>
      *
-     * @return The locale of this {@code Format}, or {@code Locale.ROOT} for unlocalized format.
+     * @return the locale of this {@code Format}, or {@code Locale.ROOT} for unlocalized format.
      */
     @Override
     public Locale getLocale() {
@@ -155,8 +155,8 @@ public abstract class CompoundFormat<T>
      *
      * For subclasses that do not override this method, the default implementation returns {@link #getLocale()}.
      *
-     * @param  category The category for which a locale is desired.
-     * @return The locale for the given category (never {@code null}).
+     * @param  category  the category for which a locale is desired.
+     * @return the locale for the given category (never {@code null}).
      *
      * @since 0.4
      */
@@ -168,7 +168,7 @@ public abstract class CompoundFormat<T>
     /**
      * Returns the timezone used by this format.
      *
-     * @return The timezone used for this format, or UTC for unlocalized format.
+     * @return the timezone used for this format, or UTC for unlocalized format.
      */
     public TimeZone getTimeZone() {
         return timezone != null ? (TimeZone) timezone.clone() : TimeZone.getTimeZone(UTC);
@@ -186,7 +186,7 @@ public abstract class CompoundFormat<T>
      *   </ul>
      * </div>
      *
-     * @return The base type of values parsed and formatted by this {@code Format} instance.
+     * @return the base type of values parsed and formatted by this {@code Format} instance.
      */
     public abstract Class<? extends T> getValueType();
 
@@ -222,10 +222,10 @@ public abstract class CompoundFormat<T>
      * This error offset policy is a consequence of the compound nature of {@code CompoundFormat},
      * since the exception may have been produced by a call to {@link Format#parseObject(String)}.
      *
-     * @param  text The character sequence for the object to parse.
-     * @param  pos  The position where to start the parsing.
-     * @return The parsed object.
-     * @throws ParseException If an error occurred while parsing the object.
+     * @param  text  the character sequence for the object to parse.
+     * @param  pos   the position where to start the parsing.
+     * @return the parsed object.
+     * @throws ParseException if an error occurred while parsing the object.
      */
     public abstract T parse(CharSequence text, ParsePosition pos) throws ParseException;
 
@@ -253,9 +253,9 @@ public abstract class CompoundFormat<T>
      * In case of failure, the {@linkplain ParseException exception error offset} is added
      * to the {@code pos} error index.
      *
-     * @param  text The string representation of the object to parse.
-     * @param  pos  The position where to start the parsing.
-     * @return The parsed object, or {@code null} if the given string can not be parsed.
+     * @param  text  the string representation of the object to parse.
+     * @param  pos   the position where to start the parsing.
+     * @return the parsed object, or {@code null} if the given string can not be parsed.
      */
     @Override
     public T parseObject(final String text, final ParsePosition pos) {
@@ -280,9 +280,9 @@ public abstract class CompoundFormat<T>
      * and {@code isISOControl(…)} done in this {@code parseObject(…)} method is more permissive since it encompasses
      * all whitespace characters, plus non-breaking spaces and non-white ISO controls.</div>
      *
-     * @param  text The string representation of the object to parse.
-     * @return The parsed object.
-     * @throws ParseException If an error occurred while parsing the object.
+     * @param  text  the string representation of the object to parse.
+     * @return the parsed object.
+     * @throws ParseException if an error occurred while parsing the object.
      */
     @Override
     public T parseObject(final String text) throws ParseException {
@@ -306,9 +306,9 @@ public abstract class CompoundFormat<T>
     /**
      * Writes a textual representation of the given object in the given stream or buffer.
      *
-     * @param  object      The object to format.
-     * @param  toAppendTo  Where to format the object.
-     * @throws IOException If an error occurred while writing to the given appendable.
+     * @param  object      the object to format.
+     * @param  toAppendTo  where to format the object.
+     * @throws IOException if an error occurred while writing to the given appendable.
      */
     public abstract void format(T object, Appendable toAppendTo) throws IOException;
 
@@ -323,10 +323,10 @@ public abstract class CompoundFormat<T>
      * method and performs some I/O operation outside the given {@link StringBuffer}. However this is not the intended
      * usage of this class and implementors should avoid such unexpected I/O operation.</div>
      *
-     * @param  object      The object to format.
-     * @param  toAppendTo  Where to format the object.
-     * @param  pos         Ignored in current implementation.
-     * @return             The given buffer, returned for convenience.
+     * @param  object      the object to format.
+     * @param  toAppendTo  where to format the object.
+     * @param  pos         ignored in current implementation.
+     * @return the given buffer, returned for convenience.
      */
     @Override
     public StringBuffer format(final Object object, final StringBuffer toAppendTo, final FieldPosition pos) {
@@ -360,14 +360,14 @@ public abstract class CompoundFormat<T>
      * See {@link #createFormat(Class)} for the list of value types recognized by the default
      * {@code CompoundFormat} implementation.
      *
-     * @param  valueType The base type of values to parse or format, or {@code null} if unknown.
-     * @return The format to use for parsing and formatting values of the given type or any
-     *         parent type, or {@code null} if none.
+     * @param  valueType  the base type of values to parse or format, or {@code null} if unknown.
+     * @return the format to use for parsing and formatting values of the given type or any parent type,
+     *         or {@code null} if none.
      */
     protected Format getFormat(final Class<?> valueType) {
         Format format = null;
         Map<Class<?>,Format> formats = this.formats;
-        for (Class<?> type=valueType; type!=null; type=type.getSuperclass()) {
+        for (Class<?> type = valueType; type != null; type = type.getSuperclass()) {
             if (formats != null) {
                 format = formats.get(type);
                 if (format != null) {
@@ -416,9 +416,8 @@ public abstract class CompoundFormat<T>
      * sub-types. For example a subclass may choose to format {@link Double} values differently
      * than other types of number.
      *
-     * @param  valueType The base type of values to parse or format.
-     * @return The format to use for parsing of formatting values of the given type,
-     *         or {@code null} if none.
+     * @param  valueType  the base type of values to parse or format.
+     * @return the format to use for parsing of formatting values of the given type, or {@code null} if none.
      */
     protected Format createFormat(final Class<?> valueType) {
         /*
@@ -462,7 +461,7 @@ public abstract class CompoundFormat<T>
     /**
      * Returns a clone of this format.
      *
-     * @return A clone of this format.
+     * @return a clone of this format.
      */
     @Override
     public CompoundFormat<T> clone() {



Mime
View raw message