sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1724531 [9/13] - in /sis/trunk: ./ application/sis-console/src/main/artifact/bin/ application/sis-console/src/main/artifact/log/ application/sis-console/src/main/java/org/apache/sis/console/ core/sis-build-helper/src/main/java/org/apache/s...
Date Wed, 13 Jan 2016 23:59:41 GMT
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/Supervisor.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/Supervisor.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/Supervisor.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/Supervisor.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -37,7 +37,6 @@ import javax.management.InstanceAlreadyE
 import java.lang.management.ManagementFactory;
 
 import org.apache.sis.setup.About;
-import org.apache.sis.util.Localized;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Messages;
@@ -52,10 +51,10 @@ import org.apache.sis.util.collection.Tr
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  */
-public final class Supervisor extends StandardMBean implements SupervisorMBean, Localized {
+public final class Supervisor extends StandardMBean implements SupervisorMBean {
     /**
      * Whatever JMX agent is enabled. Setting this variable to {@code false} allows the
      * Java compiler to omit any dependency to this {@code Supervisor} class.
@@ -82,13 +81,13 @@ public final class Supervisor extends St
      * and the MBean will not be registered. This method does not propagate the exception
      * because the MBean is not a mandatory part of SIS library.</p>
      */
-    static synchronized void register() {
+    public static synchronized void register() {
         if (name == null) {
             name = ObjectName.WILDCARD; // In case of failure.
             final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
             try {
                 final ObjectName n = new ObjectName(NAME);
-                server.registerMBean(new Supervisor(null, null), n);
+                server.registerMBean(new Supervisor(), n);
                 name = n; // Store only on success.
             } catch (InstanceAlreadyExistsException e) {
                 final LogRecord record = Messages.getResources(null)
@@ -119,34 +118,12 @@ public final class Supervisor extends St
     }
 
     /**
-     * The locale for producing the messages, or {@code null} for the default.
-     */
-    private final Locale locale;
-
-    /**
-     * The timezone for formatting the dates, or {@code null} for the default.
-     */
-    private final TimeZone timezone;
-
-    /**
-     * Creates a new {@code Supervisor} which will report messages in the given locale.
+     * Creates a new {@code Supervisor}.
      *
-     * @param  locale The locale to use for reporting messages, or {@code null} for the default.
-     * @param  timezone The timezone for formatting the dates, or {@code null} for the default.
      * @throws NotCompliantMBeanException Should never happen.
      */
-    public Supervisor(final Locale locale, final TimeZone timezone) throws NotCompliantMBeanException {
+    public Supervisor() throws NotCompliantMBeanException {
         super(SupervisorMBean.class);
-        this.locale   = locale;
-        this.timezone = timezone;
-    }
-
-    /**
-     * Returns the supervisor locale, or {@code null} for the default locale.
-     */
-    @Override
-    public Locale getLocale() {
-        return locale;
     }
 
     /**
@@ -210,7 +187,7 @@ public final class Supervisor extends St
      */
     private String getDescription(final String resourceKey) {
         return ResourceBundle.getBundle("org.apache.sis.internal.system.Descriptions",
-                (locale != null) ? locale : Locale.getDefault(),
+                Locale.getDefault(),
                 Supervisor.class.getClassLoader()).getString(resourceKey);
     }
 
@@ -222,15 +199,15 @@ public final class Supervisor extends St
      * {@inheritDoc}
      */
     @Override
-    public TreeTable configuration() {
-        return About.configuration(EnumSet.allOf(About.class), locale, timezone);
+    public TreeTable configuration(final EnumSet<About> sections, final Locale locale, final TimeZone timezone) {
+        return About.configuration(sections, locale, timezone);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public String[] warnings() {
+    public String[] warnings(final Locale locale) {
         final DaemonThread lastCreatedDaemon;
         synchronized (Threads.class) {
             lastCreatedDaemon = Threads.lastCreatedDaemon;

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/SupervisorMBean.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/SupervisorMBean.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/SupervisorMBean.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/SupervisorMBean.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -16,6 +16,10 @@
  */
 package org.apache.sis.internal.system;
 
+import java.util.EnumSet;
+import java.util.Locale;
+import java.util.TimeZone;
+import org.apache.sis.setup.About;
 import org.apache.sis.util.collection.TreeTable;
 
 
@@ -24,7 +28,7 @@ import org.apache.sis.util.collection.Tr
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 public interface SupervisorMBean {
@@ -35,15 +39,19 @@ public interface SupervisorMBean {
      * Apache SIS version, Java version and operation system version; a "Classpath"
      * section containing bootstrap, extension and user classpath, <i>etc</i>.
      *
+     * @param  sections The section for which information are desired.
+     * @param  locale   The locale to use for formatting the texts in the tree, or {@code null} for the default.
+     * @param  timezone The timezone to use for formatting the dates, or {@code null} for the default.
      * @return Configuration information, as a tree for grouping some configuration by sections.
      */
-    TreeTable configuration();
+    TreeTable configuration(EnumSet<About> sections, Locale locale, TimeZone timezone);
 
     /**
      * If there is something wrong with the current Apache SIS status,
      * returns descriptions of the problems. Otherwise returns {@code null}.
      *
+     * @param  locale The locale to use for reporting messages, or {@code null} for the default.
      * @return A description of a problems in the library, or {@code null} if none.
      */
-    String[] warnings();
+    String[] warnings(Locale locale);
 }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/Threads.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/Threads.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/Threads.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/Threads.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -16,8 +16,6 @@
  */
 package org.apache.sis.internal.system;
 
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.ExecutorService;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.logging.Logging;
 
@@ -34,7 +32,7 @@ import org.apache.sis.util.logging.Loggi
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 final class Threads extends Static {
@@ -83,19 +81,6 @@ final class Threads extends Static {
     static DaemonThread lastCreatedDaemon;
 
     /**
-     * Executor to shutdown. This is a copy of the {@code <removed class>} executor static final
-     * field, copied here only when the {@code <removed class>} class is loaded and initialized.
-     * We proceed that way for avoiding dependency from {@code Threads} to {@code <removed class>}.
-     *
-     * <p>This field has been temporarily fixed to {@code null} since we removed executor as of
-     * <a href="https://issues.apache.org/jira/browse/SIS-76">SIS-76</a>. However we may revert
-     * to a modifiable field in a future version if we choose to use executor again. In the main
-     * time, we declare this field as {@code final} for allowing the Javac compiler to omit all
-     * compiled code inside {@code if (executor != null)} block.</p>
-     */
-    private static final ExecutorService executor = null;
-
-    /**
      * Do not allows instantiation of this class.
      */
     private Threads() {
@@ -114,20 +99,6 @@ final class Threads extends Static {
      *         we were waiting for the daemon threads to die.
      */
     static synchronized void shutdown(final long stopWaitingAt) throws InterruptedException {
-        if (executor != null) {
-            executor.shutdown();
-            /*
-             * Wait for work completion. In theory this is not necessary since the daemon
-             * tasks are only house-cleaning work. We nevertheless wait for their completion
-             * as a safety. There tasks are supposed to be short.
-             */
-            final long delay = stopWaitingAt - System.nanoTime();
-            if (delay > 0) {
-                executor.awaitTermination(delay, TimeUnit.NANOSECONDS);
-                // Even if the tasks didn't completed, continue without waiting for them.
-                // We can not log at this point, since the logging framework may be shutdown.
-            }
-        }
         DaemonThread.killAll(lastCreatedDaemon, stopWaitingAt);
     }
 }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/package-info.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/package-info.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/package-info.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -25,7 +25,7 @@
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 package org.apache.sis.internal.system;

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -374,6 +374,29 @@ public abstract class AbstractMap<K,V> i
                 final EntryIterator<K,V> it = entryIterator();
                 return (it != null) ? new Keys<K,V>(it) : Collections.<K>emptySet().iterator();
             }
+
+            /** Overridden for the same reason than {@link AbstractMap#equals(Object). */
+            @Override public boolean equals(final Object object) {
+                if (object == this) {
+                    return true;
+                }
+                if (!(object instanceof Set<?>)) {
+                    return false;
+                }
+                final Set<?> that = (Set<?>) object;
+                final EntryIterator<K,V> it = entryIterator();
+                if (it == null) {
+                    return that.isEmpty();
+                }
+                int size = 0;
+                while (it.next()) {
+                    if (!that.contains(it.getKey())) {
+                        return false;
+                    }
+                    size++;
+                }
+                return size == that.size();
+            }
         };
     }
 
@@ -433,6 +456,29 @@ public abstract class AbstractMap<K,V> i
                 final EntryIterator<K,V> it = entryIterator();
                 return (it != null) ? new Entries<K,V>(it) : Collections.<Entry<K,V>>emptySet().iterator();
             }
+
+            /** Overridden for the same reason than {@link AbstractMap#equals(Object). */
+            @Override public boolean equals(final Object object) {
+                if (object == this) {
+                    return true;
+                }
+                if (!(object instanceof Set<?>)) {
+                    return false;
+                }
+                final Set<?> that = (Set<?>) object;
+                final EntryIterator<K,V> it = entryIterator();
+                if (it == null) {
+                    return that.isEmpty();
+                }
+                int size = 0;
+                while (it.next()) {
+                    if (!that.contains(it.getEntry())) {
+                        return false;
+                    }
+                    size++;
+                }
+                return size == that.size();
+            }
         };
     }
 
@@ -543,27 +589,27 @@ public abstract class AbstractMap<K,V> i
         if (object == this) {
             return true;
         }
-        if (object instanceof Map) {
-            final Map<?,?> map = (Map<?,?>) object;
-            final EntryIterator<K,V> it = entryIterator();
-            if (it == null) {
-                return map.isEmpty();
-            }
-            /*
-             * We do not check if map.size() == size() because in some Apache SIS implementations,
-             * the size() method have to scan through all map entries. We presume that if the maps
-             * are not equal, we will find a mismatched entry soon anyway.
-             */
-            int size = 0;
-            while (it.next()) {
-                if (!it.getValue().equals(map.get(it.getKey()))) {
-                    return false;
-                }
-                size++;
+        if (!(object instanceof Map<?,?>)) {
+            return false;
+        }
+        final Map<?,?> that = (Map<?,?>) object;
+        final EntryIterator<K,V> it = entryIterator();
+        if (it == null) {
+            return that.isEmpty();
+        }
+        /*
+         * We do not check if map.size() == size() because in some Apache SIS implementations,
+         * the size() method have to scan through all map entries. We presume that if the maps
+         * are not equal, we will find a mismatched entry soon anyway.
+         */
+        int size = 0;
+        while (it.next()) {
+            if (!it.getValue().equals(that.get(it.getKey()))) {
+                return false;
             }
-            return size == map.size();
+            size++;
         }
-        return false;
+        return size == that.size();
     }
 
     /**

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=1724531&r1=1724530&r2=1724531&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 Jan 13 23:59:38 2016
@@ -32,7 +32,7 @@ import org.apache.sis.util.Static;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public final class Constants extends Static {
@@ -78,6 +78,16 @@ public final class Constants extends Sta
     public static final byte CRS84 = 84;
 
     /**
+     * The {@code CRS:88} identifier for a coordinate reference system.
+     */
+    public static final byte CRS88 = 88;
+
+    /**
+     * The {@code CRS:1} identifier for a coordinate reference system.
+     */
+    public static final byte CRS1 = 1;
+
+    /**
      * The NetCDF parameter name for the Earth radius.
      */
     public static final String EARTH_RADIUS = "earth_radius";
@@ -101,6 +111,11 @@ public final class Constants extends Sta
     public static final String CENTRAL_MERIDIAN = "central_meridian";
 
     /**
+     * The OGC parameter name for the latitude of origin.
+     */
+    public static final String LATITUDE_OF_ORIGIN = "latitude_of_origin";
+
+    /**
      * The NetCDF parameter name for the standard parallels.
      */
     public static final String STANDARD_PARALLEL = "standard_parallel";
@@ -169,6 +184,21 @@ public final class Constants extends Sta
     public static final short EPSG_B0 = 8639;
 
     /**
+     * The EPSG code for metres.
+     */
+    public static final short EPSG_METRE = 9001;
+
+    /**
+     * The EPSG code for degrees when used in parameters.
+     */
+    public static final short EPSG_PARAM_DEGREES = 9102;
+
+    /**
+     * The EPSG code for degrees when used in axes.
+     */
+    public static final short EPSG_AXIS_DEGREES = 9122;
+
+    /**
      * Do not allow instantiation of this class.
      */
     private Constants() {

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -21,6 +21,9 @@ import org.apache.sis.math.MathFunctions
 import org.apache.sis.math.DecimalFunctions;
 // No BigDecimal dependency - see class javadoc
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk8.JDK8;
+
 
 /**
  * Basic arithmetic methods for extended precision numbers using the <cite>double-double</cite> algorithm.
@@ -284,7 +287,7 @@ public final class DoubleDouble extends
     @Override public double doubleValue() {return value;}
     @Override public float  floatValue()  {return (float) value;}
     @Override public long   longValue()   {return Math.round(value);}
-    @Override public int    intValue()    {return (int) longValue();}
+    @Override public int    intValue()    {return JDK8.toIntExact(longValue());}
 
     /**
      * Suggests an {@link #error} for the given value. The {@code DoubleDouble} class contains a hard-coded list

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -25,6 +25,9 @@ import org.apache.sis.util.ComparisonMod
 import static java.lang.Math.max;
 import static java.lang.Math.abs;
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk8.JDK8;
+
 
 /**
  * Miscellaneous utilities methods working on floating point numbers.
@@ -180,7 +183,7 @@ public final class Numerics extends Stat
         if (data == null) return null;
         final int[] result = new int[data.length];
         for (int i=0; i<data.length; i++) {
-            result[i] = (int) Math.round(data[i]);
+            result[i] = JDK8.toIntExact(Math.round(data[i]));
         }
         return result;
     }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -120,6 +120,7 @@ public enum X364 {
      * @param code  The X.364 numerical code.
      * @param color The color name, or {@code null} if none.
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     private X364(final byte code, final String color) {
         this.code  = code;
         this.color = color;
@@ -132,6 +133,7 @@ public enum X364 {
      *
      * @param foreground The X.364 code for a foreground color.
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     private X364(final X364 foreground) {
         this((byte) (foreground.code + 10), foreground.color);
         this.foreground = foreground;

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Line.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Line.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Line.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Line.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -28,8 +28,8 @@ import static java.lang.Double.*;
 
 /**
  * Equation of a line in a two dimensional space (<var>x</var>,<var>y</var>).
- * A line can be expressed by the <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y</var>₀ equation
- * where <var>y</var>₀ is the value of <var>y</var> at <var>x</var> = 0.
+ * A line can be expressed by the <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y₀</var> equation
+ * where <var>y₀</var> is the value of <var>y</var> at <var>x</var> = 0.
  *
  * <p>The equation parameters for a {@code Line} object can be set at construction time or using one
  * of the {@code setLine(…)} methods. The <var>y</var> value can be computed for a given <var>x</var>
@@ -37,8 +37,8 @@ import static java.lang.Double.*;
  * work even if the line is vertical.</p>
  *
  * <div class="note"><b>Comparison with Java2D geometries:</b>
- * At the difference of {@link java.awt.geom.Line2D} which is bounded by (<var>x</var>₁,<var>y</var>₁)
- * and (<var>x</var>₂,<var>y</var>₂) points, {@code Line} objects extend toward infinity.</div>
+ * At the difference of {@link java.awt.geom.Line2D} which is bounded by (<var>x₁</var>,<var>y₁</var>)
+ * and (<var>x₂</var>,<var>y₂</var>) points, {@code Line} objects extend toward infinity.</div>
  *
  * @author  Martin Desruisseaux (MPO, IRD)
  * @since   0.5
@@ -84,7 +84,7 @@ public class Line implements Cloneable,
 
     /**
      * Constructs a line with the specified slope and offset.
-     * The linear equation will be <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y</var>₀.
+     * The linear equation will be <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y₀</var>.
      *
      * @param slope The slope.
      * @param y0 The <var>y</var> value at <var>x</var> = 0.
@@ -111,7 +111,7 @@ public class Line implements Cloneable,
 
     /**
      * Returns the <var>x</var> value for <var>y</var> = 0.
-     * Coordinate (<var>x</var>₀, 0) is the intersection point with the <var>x</var> axis.
+     * Coordinate (<var>x₀</var>, 0) is the intersection point with the <var>x</var> axis.
      *
      * @return The <var>x</var> value for <var>y</var> = 0.
      *
@@ -137,7 +137,7 @@ public class Line implements Cloneable,
 
     /**
      * Returns the <var>y</var> value for <var>x</var> = 0.
-     * Coordinate (0, <var>y</var>₀) is the intersection point with the <var>y</var> axis.
+     * Coordinate (0, <var>y₀</var>) is the intersection point with the <var>y</var> axis.
      *
      * @return The <var>y</var> value for <var>x</var> = 0.
      *
@@ -179,7 +179,7 @@ public class Line implements Cloneable,
 
     /**
      * Sets this line to the specified slope and offset.
-     * The linear equation will be <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y</var>₀.
+     * The linear equation will be <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y₀</var>.
      *
      * @param slope The slope.
      * @param y0 The <var>y</var> value at <var>x</var> = 0.
@@ -218,7 +218,7 @@ public class Line implements Cloneable,
 
     /**
      * Given a set of data points <var>x</var>[0 … <var>n</var>-1], <var>y</var>[0 … <var>n</var>-1],
-     * fits them to a straight line <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y</var>₀ in a
+     * fits them to a straight line <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y₀</var> in a
      * least-squares senses. This method assume that the <var>x</var> values are precise and all uncertainty
      * is in <var>y</var>.
      *
@@ -235,7 +235,7 @@ public class Line implements Cloneable,
 
     /**
      * Given a sequence of points, fits them to a straight line <var>y</var> = <var>slope</var>⋅<var>x</var> +
-     * <var>y</var>₀ in a least-squares senses. This method assume that the <var>x</var> values are precise and
+     * <var>y₀</var> in a least-squares senses. This method assume that the <var>x</var> values are precise and
      * all uncertainty is in <var>y</var>.
      *
      * <p>Points shall be two dimensional with ordinate values in the (<var>x</var>,<var>y</var>) order.
@@ -382,7 +382,7 @@ public class Line implements Cloneable,
 
     /**
      * Returns a string representation of this line. This method returns the linear equation
-     * in the form <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y</var>₀.
+     * in the form <var>y</var> = <var>slope</var>⋅<var>x</var> + <var>y₀</var>.
      *
      * @return A string representation of this line.
      */

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -35,7 +35,7 @@ import static java.lang.Math.ulp;
  *
  * <blockquote>
  *   <var>{@linkplain #z(double, double) z}</var>(<var>x</var>,<var>y</var>) =
- *   <var>sx</var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <var>z</var>₀
+ *   <var>sx</var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <var>z₀</var>
  * </blockquote>
  *
  * Those coefficients can be set directly, or computed by a linear regression of this plane
@@ -83,19 +83,19 @@ public class Plane implements Cloneable,
 
     /**
      * The slope along the <var>x</var> values. This coefficient appears in the plane equation
-     * <var><b><u>sx</u></b></var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <var>z</var>₀.
+     * <var><b><u>sx</u></b></var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <var>z₀</var>.
      */
     private double sx;
 
     /**
      * The slope along the <var>y</var> values. This coefficient appears in the plane equation
-     * <var>sx</var>⋅<var>x</var> + <var><b><u>sy</u></b></var>⋅<var>y</var> + <var>z</var>₀.
+     * <var>sx</var>⋅<var>x</var> + <var><b><u>sy</u></b></var>⋅<var>y</var> + <var>z₀</var>.
      */
     private double sy;
 
     /**
      * The <var>z</var> value at (<var>x</var>,<var>y</var>) = (0,0). This coefficient appears in the plane equation
-     * <var>sx</var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <b><u><var>z</var>₀</u></b>.
+     * <var>sx</var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <b><u><var>z₀</var></u></b>.
      */
     private double z0;
 
@@ -123,7 +123,7 @@ public class Plane implements Cloneable,
 
     /**
      * Returns the slope along the <var>x</var> values. This coefficient appears in the plane equation
-     * <var><b><u>sx</u></b></var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <var>z</var>₀.
+     * <var><b><u>sx</u></b></var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <var>z₀</var>.
      *
      * @return The <var>sx</var> term.
      */
@@ -133,7 +133,7 @@ public class Plane implements Cloneable,
 
     /**
      * Returns the slope along the <var>y</var> values. This coefficient appears in the plane equation
-     * <var>sx</var>⋅<var>x</var> + <var><b><u>sy</u></b></var>⋅<var>y</var> + <var>z</var>₀.
+     * <var>sx</var>⋅<var>x</var> + <var><b><u>sy</u></b></var>⋅<var>y</var> + <var>z₀</var>.
      *
      * @return The <var>sy</var> term.
      */
@@ -143,9 +143,9 @@ public class Plane implements Cloneable,
 
     /**
      * Returns the <var>z</var> value at (<var>x</var>,<var>y</var>) = (0,0). This coefficient appears in the
-     * plane equation <var>sx</var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <b><var>z</var>₀</b>.
+     * plane equation <var>sx</var>⋅<var>x</var> + <var>sy</var>⋅<var>y</var> + <b><var>z₀</var></b>.
      *
-     * @return The <var>z</var>₀ term.
+     * @return The <var>z₀</var> term.
      *
      * @see #z(double, double)
      */

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Statistics.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Statistics.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Statistics.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/Statistics.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -429,7 +429,7 @@ public class Statistics implements Doubl
     /**
      * Returns the standard deviation. If the sample values given to the {@code accept(…)}
      * methods have a uniform distribution, then the returned value should be close to
-     * <code>sqrt({@linkplain #span() span}<sup>2</sup> / 12)</code>. If they have a
+     * <code>sqrt({@linkplain #span() span}² / 12)</code>. If they have a
      * Gaussian distribution (which is the most common case), then the returned value
      * is related to the <a href="http://en.wikipedia.org/wiki/Error_function">error
      * function</a>.

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -43,6 +43,7 @@ import static org.apache.sis.math.Decima
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk7.Objects;
+import org.apache.sis.internal.jdk8.JDK8;
 
 
 /**
@@ -1044,12 +1045,12 @@ public class AngleFormat extends Format
                 }
                 final Number userObject;
                 if (hasMore) {
-                    userObject = Integer.valueOf((int) Math.round(value));
+                    userObject = JDK8.toIntExact(Math.round(value));
                 } else {
                     // Use Float instead of Double because we don't want to give a false impression of accuracy
                     // (when formatting the seconds field, at least the 10 last bits of the 'double' value are
                     // non-significant).
-                    userObject = Float.valueOf((float) value);
+                    userObject = (float) value;
                 }
                 it.addFieldLimit(Field.forCode(field), userObject, startPosition);
             } else {

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/Longitude.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/Longitude.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/Longitude.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/Longitude.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -110,6 +110,8 @@ public final class Longitude extends Ang
      *   <li>±0 are returned unchanged (i.e. the sign of negative and positive zero is preserved)</li>
      * </ul>
      *
+     * Note that the given value should not be greater than 4×10⁸ degrees if a centimetric precision is desired.
+     *
      * @param  λ The longitude value in decimal degrees.
      * @return The given value normalized to the [-180 … 180)° range, or NaN if the given value was NaN of infinite.
      *

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -47,7 +47,7 @@ import static org.apache.sis.util.CharSe
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  */
 public final class Units extends Static {
@@ -70,6 +70,11 @@ public final class Units extends Static
     public static final Unit<Duration> MILLISECOND = SI.MetricPrefix.MILLI(SI.SECOND);
 
     /**
+     * The EPSG::1029 definition of year.
+     */
+    private static final Unit<Duration> YEAR = SI.SECOND.divide(31556925.445);
+
+    /**
      * Parts per million.
      *
      * <p>This unit does not have an easily readable symbol because of the
@@ -242,27 +247,27 @@ public final class Units extends Static
      *   <li>This method tries to returns unique instances for some common units.</li>
      * </ul>
      *
-     * @param  <A>    The quantity measured by the unit.
+     * @param  <Q>    The quantity measured by the unit.
      * @param  unit   The unit to multiply.
      * @param  factor The multiplication factor.
      * @return The unit multiplied by the given factor.
      */
     @Workaround(library="JSR-275", version="0.9.3")
     @SuppressWarnings("unchecked")
-    public static <A extends Quantity> Unit<A> multiply(Unit<A> unit, final double factor) {
+    public static <Q extends Quantity> Unit<Q> multiply(Unit<Q> unit, final double factor) {
         if (SI.RADIAN.equals(unit)) {
             if (abs(factor - (PI / 180)) <= (EPS * PI/180)) {
-                return (Unit<A>) NonSI.DEGREE_ANGLE;
+                return (Unit<Q>) NonSI.DEGREE_ANGLE;
             }
             if (abs(factor - (PI / 200)) <= (EPS * PI/200)) {
-                return (Unit<A>) NonSI.GRADE;
+                return (Unit<Q>) NonSI.GRADE;
             }
         } else if (SI.METRE.equals(unit)) {
             if (abs(factor - 0.3048) <= (EPS * 0.3048)) {
-                return (Unit<A>) NonSI.FOOT;
+                return (Unit<Q>) NonSI.FOOT;
             }
             if (abs(factor - (1200.0/3937)) <= (EPS * (1200.0/3937))) {
-                return (Unit<A>) NonSI.FOOT_SURVEY_US;
+                return (Unit<Q>) NonSI.FOOT_SURVEY_US;
             }
         }
         if (abs(factor - 1) > EPS) {
@@ -289,13 +294,13 @@ public final class Units extends Static
      * since a measurement in kilometres must be multiplied by 1000 in order to give the equivalent
      * measurement in the "standard" units (here <var>metres</var>).</p>
      *
-     * @param  <A>  The quantity measured by the unit.
+     * @param  <Q>  The quantity measured by the unit.
      * @param  unit The unit for which we want the multiplication factor to standard unit.
      * @return The factor by which to multiply a measurement in the given unit in order to
      *         get an equivalent measurement in the standard unit.
      */
     @Workaround(library="JSR-275", version="0.9.3")
-    public static <A extends Quantity> double toStandardUnit(final Unit<A> unit) {
+    public static <Q extends Quantity> double toStandardUnit(final Unit<Q> unit) {
         return derivative(unit.getConverterTo(unit.toSI()), 0);
     }
 
@@ -364,7 +369,7 @@ public final class Units extends Static
          */
         if (isURI(uom)) {
             String code = DefinitionURI.codeOf("uom", Constants.EPSG, uom);
-            if (code != null && code != uom) try { // Really identity check, see above comment.
+            if (code != null && code != uom) try {              // Really identity check, see above comment.
                 return valueOfEPSG(Integer.parseInt(code));
             } catch (NumberFormatException e) {
                 throw new IllegalArgumentException(Errors.format(
@@ -493,28 +498,22 @@ public final class Units extends Static
      * and some frequently-used units. The list of recognized units may be updated in any future
      * version of SIS.</p>
      *
-     * <p>The {@link org.apache.sis.referencing.factory.epsg.DirectEpsgFactory} uses this method
+     * <p>The {@link org.apache.sis.referencing.factory.sql.EPSGDataAccess} class uses this method
      * for fetching the base units, and derives automatically other units from the information
      * found in the EPSG database. This method is also used by other classes not directly related
-     * to the EPSG database, like {@link org.apache.sis.referencing.factory.web.AutoCRSFactory}
+     * to the EPSG database, like {@link org.apache.sis.referencing.factory.CommonAuthorityFactory}
      * which uses EPSG code for identifying units.</p>
      *
      * <p>The currently recognized values are:</p>
      * <table class="sis">
      *   <caption>EPSG codes for units</caption>
      *   <tr>
-     *     <th>Linear units</th>
-     *     <th class="sep">Angular units</th>
+     *     <th>Angular units</th>
+     *     <th class="sep">Linear units</th>
+     *     <th class="sep">Temporal units</th>
      *     <th class="sep">Scale units</th>
      *   </tr><tr>
-     *     <td><table class="compact" summary="Linear units">
-     *       <tr><td style="width: 40px"><b>Code</b></td><td><b>Unit</b></td></tr>
-     *       <tr><td>9001</td><td>metre</td></tr>
-     *       <tr><td>9002</td><td>foot</td></tr>
-     *       <tr><td>9030</td><td>nautical mile</td></tr>
-     *       <tr><td>9036</td><td>kilometre</td></tr>
-     *     </table></td>
-     *     <td class="sep"><table class="compact" summary="Angular units">
+     *     <td><table class="compact" summary="Angular units">
      *       <tr><td style="width: 40px"><b>Code</b></td><td><b>Unit</b></td></tr>
      *       <tr><td>9101</td><td>radian</td></tr>
      *       <tr><td>9102</td><td>decimal degree</td></tr>
@@ -528,6 +527,19 @@ public final class Units extends Static
      *       <tr><td>9111</td><td>sexagesimal degree-minute</td></tr>
      *       <tr><td>9122</td><td>decimal degree</td></tr>
      *     </table></td>
+     *     <td class="sep"><table class="compact" summary="Linear units">
+     *       <tr><td style="width: 40px"><b>Code</b></td><td><b>Unit</b></td></tr>
+     *       <tr><td>9001</td><td>metre</td></tr>
+     *       <tr><td>9002</td><td>foot</td></tr>
+     *       <tr><td>9003</td><td>US survey foot</td></tr>
+     *       <tr><td>9030</td><td>nautical mile</td></tr>
+     *       <tr><td>9036</td><td>kilometre</td></tr>
+     *     </table></td>
+     *     <td class="sep"><table class="compact" summary="Time units">
+     *       <tr><td style="width: 40px"><b>Code</b></td><td><b>Unit</b></td></tr>
+     *       <tr><td>1029</td><td>year</td></tr>
+     *       <tr><td>1040</td><td>second</td></tr>
+     *     </table></td>
      *     <td class="sep"><table class="compact" summary="Scale units">
      *       <tr><td style="width: 40px"><b>Code</b></td><td><b>Unit</b></td></tr>
      *       <tr><td>9201</td><td>one</td></tr>
@@ -544,16 +556,22 @@ public final class Units extends Static
      *
      * @param  code The EPSG code for a unit of measurement.
      * @return The unit, or {@code null} if the code is unrecognized.
+     *
+     * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createUnit(String)
      */
     public static Unit<?> valueOfEPSG(final int code) {
         switch (code) {
-            case 9001: return SI   .METRE;
+            case Constants.EPSG_PARAM_DEGREES:  // Fall through
+            case Constants.EPSG_AXIS_DEGREES:   return NonSI.DEGREE_ANGLE;
+            case Constants.EPSG_METRE:          return SI.METRE;
+
+            case 1029: return       YEAR;
+            case 1040: return SI   .SECOND;
             case 9002: return NonSI.FOOT;
+            case 9003: return NonSI.FOOT_SURVEY_US;
             case 9030: return NonSI.NAUTICAL_MILE;
             case 9036: return SI   .KILOMETRE;
             case 9101: return SI   .RADIAN;
-            case 9122: // Fall through
-            case 9102: return NonSI.DEGREE_ANGLE;
             case 9103: return NonSI.MINUTE_ANGLE;
             case 9104: return NonSI.SECOND_ANGLE;
             case 9105: return NonSI.GRADE;
@@ -575,8 +593,8 @@ public final class Units extends Static
      *
      * <p>The same unit may be represented by different EPSG codes depending on the context:</p>
      * <ul>
-     *   <li>EPSG:9102 – <cite>degree</cite> – is used for prime meridian and coordinate operation parameters.</li>
-     *   <li>EPSG:9122 – <cite>degree (supplier to define representation)</cite> – is used for coordinate system axes.</li>
+     *   <li>EPSG::9102 – <cite>degree</cite> – is used for prime meridian and coordinate operation parameters.</li>
+     *   <li>EPSG::9122 – <cite>degree (supplier to define representation)</cite> – is used for coordinate system axes.</li>
      * </ul>
      *
      * When such choice exists, the code to return is determined by the {@code inAxis} argument,
@@ -590,8 +608,8 @@ public final class Units extends Static
      */
     public static Integer getEpsgCode(final Unit<?> unit, final boolean inAxis) {
         Integer code = UnitsMap.EPSG_CODES.get(unit);
-        if (inAxis && code != null && code == 9102) {
-            code = UnitsMap.I9122;
+        if (inAxis && code != null && code == Constants.EPSG_PARAM_DEGREES) {
+            code = UnitsMap.EPSG_AXIS_DEGREES;
         }
         return code;
     }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -24,6 +24,7 @@ import javax.measure.unit.SI;
 import javax.measure.unit.NonSI;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Quantity;
+import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.Static;
 
 import static org.apache.sis.measure.Units.*;
@@ -49,7 +50,7 @@ final class UnitsMap extends Static {
      * The 9122 integer, used as an alternative code for the degrees unit.
      * See {@link Units#getEpsgCode(Unit, boolean)} for more information.
      */
-    static final Integer I9122 = 9122;
+    static final Integer EPSG_AXIS_DEGREES = (int) Constants.EPSG_AXIS_DEGREES;
 
     /**
      * EPSG codes of some units. This map is the reverse of {@link Units#valueOfEPSG(int)}.

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/setup/About.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/setup/About.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/setup/About.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/setup/About.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -30,6 +30,7 @@ import java.util.MissingResourceExceptio
 import java.util.jar.Attributes;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
+import java.util.logging.Level;
 import java.io.File;
 import java.io.FileFilter;
 import java.io.IOException;
@@ -42,17 +43,23 @@ import org.apache.sis.util.CharSequences
 import org.apache.sis.util.Version;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.logging.LoggerFactory;
+import org.apache.sis.util.resources.Messages;
 import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.util.collection.TreeTable;
 import org.apache.sis.util.collection.TreeTables;
 import org.apache.sis.util.collection.DefaultTreeTable;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.system.Modules;
+import org.apache.sis.internal.system.Shutdown;
+import org.apache.sis.internal.system.DataDirectory;
 
 import static java.lang.System.getProperty;
 import static org.apache.sis.util.collection.TableColumn.NAME;
 import static org.apache.sis.util.collection.TableColumn.VALUE_AS_TEXT;
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk7.Path;
+
 
 /**
  * Provides information about the Apache SIS running environment.
@@ -71,7 +78,7 @@ import static org.apache.sis.util.collec
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 public enum About {
@@ -112,6 +119,8 @@ public enum About {
      * <ul>
      *   <li>User directory</li>
      *   <li>Default directory</li>
+     *   <li>SIS data directory</li>
+     *   <li>Temporary directory</li>
      *   <li>Java home directory</li>
      * </ul>
      */
@@ -189,10 +198,10 @@ public enum About {
         TreeTable.Node section = null;
         About newSection = VERSIONS;
 fill:   for (int i=0; ; i++) {
-            short    nameKey  = 0;    // The Vocabulary.Key for 'name', used only if name is null.
-            String   name     = null; // The value to put in the 'Name' column of the table.
-            Object   value    = null; // The value to put in the 'Value' column of the table.
-            String[] children = null; // Optional children to write below the node.
+            short    nameKey  = 0;          // The Vocabulary.Key for 'name', used only if name is null.
+            String   name     = null;       // The value to put in the 'Name' column of the table.
+            Object   value    = null;       // The value to put in the 'Value' column of the table.
+            String[] children = null;       // Optional children to write below the node.
             switch (i) {
                 case 0: {
                     if (sections.contains(VERSIONS)) {
@@ -217,6 +226,13 @@ fill:   for (int i=0; ; i++) {
                     break;
                 }
                 case 3: {
+                    if (sections.contains(VERSIONS)) {
+                        nameKey = Vocabulary.Keys.Container;
+                        value = Shutdown.getContainer();        // Sometime contains version information.
+                    }
+                    break;
+                }
+                case 4: {
                     newSection = LOCALIZATION;
                     if (sections.contains(LOCALIZATION)) {
                         final Locale current = Locale.getDefault();
@@ -231,7 +247,7 @@ fill:   for (int i=0; ; i++) {
                     }
                     break;
                 }
-                case 4: {
+                case 5: {
                     if (sections.contains(LOCALIZATION)) {
                         final TimeZone current = TimeZone.getDefault();
                         if (current != null) {
@@ -252,7 +268,7 @@ fill:   for (int i=0; ; i++) {
                     }
                     break;
                 }
-                case 5: {
+                case 6: {
                     if (sections.contains(LOCALIZATION)) {
                         nameKey = Vocabulary.Keys.CurrentDateTime;
                         final DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, formatLocale);
@@ -263,7 +279,7 @@ fill:   for (int i=0; ; i++) {
                     }
                     break;
                 }
-                case 6: {
+                case 7: {
                     if (sections.contains(LOCALIZATION)) {
                         final Charset current = Charset.defaultCharset();
                         if (current != null) {
@@ -283,7 +299,7 @@ fill:   for (int i=0; ; i++) {
                     }
                     break;
                 }
-                case 7: {
+                case 8: {
                     newSection = LOGGING;
                     if (sections.contains(LOGGING)) {
                         nameKey = Vocabulary.Keys.Implementation;
@@ -292,7 +308,24 @@ fill:   for (int i=0; ; i++) {
                     }
                     break;
                 }
-                case 8: {
+                case 9: {
+                    if (sections.contains(LOGGING)) {
+                        nameKey = Vocabulary.Keys.Level;
+                        final Level level = Logging.getLogger("").getLevel();   // Root logger level.
+                        value = level.getLocalizedName();
+                        final Map<String,Level> levels = Loggers.getEffectiveLevels();
+                        if (levels.size() != 1 || !level.equals(levels.get(Loggers.ROOT))) {
+                            int j = 0;
+                            children = new String[levels.size() * 2];
+                            for (final Map.Entry<String,Level> entry : levels.entrySet()) {
+                                children[j++] = entry.getKey();
+                                children[j++] = entry.getValue().getLocalizedName();
+                            }
+                        }
+                    }
+                    break;
+                }
+                case 10: {
                     newSection = PATHS;
                     if (sections.contains(PATHS)) {
                         nameKey = Vocabulary.Keys.UserHome;
@@ -300,28 +333,45 @@ fill:   for (int i=0; ; i++) {
                     }
                     break;
                 }
-                case 9: {
+                case 11: {
                     if (sections.contains(PATHS)) {
                         nameKey = Vocabulary.Keys.CurrentDirectory;
                         value = getProperty("user.dir");
                     }
                     break;
                 }
-                case 10: {
+                case 12: {
+                    if (sections.contains(PATHS)) {
+                        nameKey = Vocabulary.Keys.DataDirectory;
+                        value = System.getenv(DataDirectory.ENV);
+                        if (value == null) {
+                            value = Messages.getResources(locale).getString(Messages.Keys.DataDirectoryNotSpecified_1, DataDirectory.ENV);
+                        } else {
+                            final Path path = DataDirectory.getRootDirectory();
+                            if (path != null) {
+                                value = path.toString();
+                            } else {
+                                value = value + " (" + resources.getString(Vocabulary.Keys.Invalid) + ')';
+                            }
+                        }
+                    }
+                    break;
+                }
+                case 13: {
                     if (sections.contains(PATHS)) {
                         nameKey = Vocabulary.Keys.TemporaryFiles;
                         value = getProperty("java.io.tmpdir");
                     }
                     break;
                 }
-                case 11: {
+                case 14: {
                     if (sections.contains(PATHS)) {
                         nameKey = Vocabulary.Keys.JavaHome;
                         value = javaHome = getProperty("java.home");
                     }
                     break;
                 }
-                case 12: {
+                case 15: {
                     newSection = LIBRARIES;
                     if (sections.contains(LIBRARIES)) {
                         nameKey = Vocabulary.Keys.JavaExtensions;
@@ -329,7 +379,7 @@ fill:   for (int i=0; ; i++) {
                     }
                     break;
                 }
-                case 13: {
+                case 16: {
                     if (sections.contains(LIBRARIES)) {
                         nameKey = Vocabulary.Keys.Classpath;
                         value = classpath(getProperty("java.class.path"), false);

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -77,7 +77,7 @@ import static org.apache.sis.internal.jd
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  *
  * @see StringBuilders
@@ -400,7 +400,7 @@ search:     for (; fromIndex <= toIndex;
             }
             char head = (char) toSearch;
             char tail = (char) 0;
-            if (head != toSearch) { // Outside BMP plane?
+            if (head != toSearch) {                     // Outside BMP plane?
                 head = highSurrogate(toSearch);
                 tail = lowSurrogate (toSearch);
                 toIndex--;
@@ -580,7 +580,7 @@ search:     for (; fromIndex <= toIndex;
      *
      * <p>Special cases:</p>
      * <ul>
-     *   <li>If {@code toIndex} is lower than {@code toIndex},
+     *   <li>If {@code fromIndex} is lower than {@code toIndex},
      *       then this method unconditionally returns {@code toIndex}.</li>
      *   <li>If the given range contains only space characters and the character at {@code fromIndex}
      *       is the low surrogate of a valid supplementary code point, then this method returns
@@ -1327,12 +1327,13 @@ searchWordBreak:    while (true) {
     }
 
     /**
-     * Creates an acronym from the given text. If every characters in the given text are upper
-     * case, then the text is returned unchanged on the assumption that it is already an acronym.
-     * Otherwise this method returns a string containing the first character of each word, where
-     * the words are separated by the camel case convention, the {@code '_'} character, or any
-     * character which is not a {@linkplain Character#isUnicodeIdentifierPart(int) Unicode
-     * identifier part} (including spaces).
+     * Creates an acronym from the given text. This method returns a string containing the first character of each word,
+     * where the words are separated by the camel case convention, the {@code '_'} character, or any character which is
+     * not a {@linkplain Character#isUnicodeIdentifierPart(int) Unicode identifier part} (including spaces).
+     *
+     * <p>An exception to the above rule happens if the given text is a Unicode identifier without the {@code '_'}
+     * character, and every characters are upper case. In such case the text is returned unchanged on the assumption
+     * that it is already an acronym.</p>
      *
      * <p><b>Examples:</b> given {@code "northEast"}, this method returns {@code "NE"}.
      * Given {@code "Open Geospatial Consortium"}, this method returns {@code "OGC"}.</p>
@@ -1342,9 +1343,9 @@ searchWordBreak:    while (true) {
      */
     public static CharSequence camelCaseToAcronym(CharSequence text) {
         text = trimWhitespaces(text);
-        if (text != null && !isUpperCase(text, 0, text.length())) {
+        if (text != null && !isAcronym(text)) {
             final int length = text.length();
-            final StringBuilder buffer = new StringBuilder(8); // Acronyms are usually short.
+            final StringBuilder buffer = new StringBuilder(8);              // Acronyms are usually short.
             boolean wantChar = true;
             for (int i=0; i<length;) {
                 final int c = codePointAt(text, i);
@@ -1371,7 +1372,7 @@ searchWordBreak:    while (true) {
                  * first one is upper-case as well. This is for handling the identifiers which
                  * are compliant to Java-Beans convention (e.g. "northEast").
                  */
-                if (isUpperCase(buffer, 1, acrlg)) {
+                if (isUpperCase(buffer, 1, acrlg, true)) {
                     final int c = buffer.codePointAt(0);
                     final int up = toUpperCase(c);
                     if (c != up) {
@@ -1498,6 +1499,16 @@ cmp:    while (ia < lga) {
     }
 
     /**
+     * Returns {@code true} if the given text is presumed to be an acronym. Acronyms are presumed
+     * to be valid Unicode identifiers in all upper-case letters and without the {@code '_'} character.
+     *
+     * @see #camelCaseToAcronym(CharSequence)
+     */
+    private static boolean isAcronym(final CharSequence text) {
+        return isUpperCase(text) && indexOf(text, '_', 0, text.length()) < 0 && isUnicodeIdentifier(text);
+    }
+
+    /**
      * Returns {@code true} if the given identifier is a legal Unicode identifier.
      * This method returns {@code true} if the identifier length is greater than zero,
      * the first character is a {@linkplain Character#isUnicodeIdentifierStart(int)
@@ -1560,27 +1571,43 @@ cmp:    while (ia < lga) {
     }
 
     /**
-     * Returns {@code true} if every characters in the given sequence are
-     * {@linkplain Character#isUpperCase(int) upper-case} letters.
-     *
-     * <div class="note"><b>Note:</b>
-     * The behavior of this method regarding digits and punctuation is unspecified
-     * and may change in future versions.</div>
+     * Returns {@code true} if the given text is non-null, contains at least one upper-case character and
+     * no lower-case character. Space and punctuation are ignored.
      *
-     * @param  text The character sequence to test.
-     * @return {@code true} if every character are upper-case.
+     * @param  text The character sequence to test (may be {@code null}).
+     * @return {@code true} if non-null, contains at least one upper-case character and no lower-case character.
      *
      * @see String#toUpperCase()
+     *
+     * @since 0.7
      */
-    static boolean isUpperCase(final CharSequence text, int lower, final int upper) {
+    public static boolean isUpperCase(final CharSequence text) {
+        return isUpperCase(text, 0, length(text), false);
+    }
+
+    /**
+     * Returns {@code true} if the given sub-sequence is non-null, contains at least one upper-case character and
+     * no lower-case character. Space and punctuation are ignored.
+     *
+     * @param  text  The character sequence to test.
+     * @param  lower Index of the first character to check, inclusive.
+     * @param  upper Index of the last character to check, exclusive.
+     * @param  hasUpperCase {@code true} if this method should behave as if the given text already had
+     *         at least one upper-case character (not necessarily in the portion given by the indices).
+     * @return {@code true} if contains at least one upper-case character and no lower-case character.
+     */
+    private static boolean isUpperCase(final CharSequence text, int lower, final int upper, boolean hasUpperCase) {
         while (lower < upper) {
             final int c = codePointAt(text, lower);
-            if (!Character.isUpperCase(c)) {
+            if (Character.isLowerCase(c)) {
                 return false;
             }
+            if (!hasUpperCase) {
+                hasUpperCase = Character.isUpperCase(c);
+            }
             lower += charCount(c);
         }
-        return true;
+        return hasUpperCase;
     }
 
     /**

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -31,6 +31,7 @@ package org.apache.sis.util;
  *   <li>{@link #IGNORE_METADATA} – Only the attributes relevant to the object functionality are compared.</li>
  *   <li>{@link #APPROXIMATIVE}   – Only the attributes relevant to the object functionality are compared,
  *                                  with some tolerance threshold on numerical values.</li>
+ *   <li>{@link #ALLOW_VARIANT}   – For objects not really equal but related (e.g. CRS using different axis order).</li>
  *   <li>{@link #DEBUG}           – Special mode for figuring out why two objects expected to be equal are not.</li>
  * </ol>
  *
@@ -41,7 +42,7 @@ package org.apache.sis.util;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see LenientComparable#equals(Object, ComparisonMode)
@@ -69,9 +70,8 @@ public enum ComparisonMode {
     STRICT,
 
     /**
-     * Only the attributes published in some contract (typically a GeoAPI interface) need
-     * to be compared. The implementation classes do not need to be the same and some private
-     * attributes may be ignored.
+     * Only the attributes published in some contract (typically a GeoAPI interface) need to be compared.
+     * The implementation classes do not need to be the same and some private attributes may be ignored.
      *
      * <p>Note that this comparison mode does <strong>not</strong> guaranteed {@link Object#hashCode()}
      * consistency, neither comparison symmetry (i.e. {@code A.equals(B)} and {@code B.equals(A)} may
@@ -93,25 +93,24 @@ public enum ComparisonMode {
      * are only informative can be ignored. This comparison mode is typically less strict than
      * {@link #BY_CONTRACT}.
      *
-     * <div class="section">Examples</div>
-     * If the objects being compared are
-     * {@link org.opengis.referencing.crs.CoordinateReferenceSystem} instances, then only the
-     * properties relevant to the coordinate localization shall be compared. Metadata like the
-     * {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem#getIdentifiers() identifiers}
-     * or the {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem#getDomainOfValidity()
-     * domain of validity}, which have no impact on the coordinates being calculated, shall be ignored.
-     *
-     * <p>If the objects being compared are {@link org.opengis.referencing.operation.MathTransform}
-     * instances, then two transforms defined in a different way may be considered equivalent.
-     * For example it is possible to define a
-     * {@linkplain org.apache.sis.referencing.operation.projection.Mercator Mercator} projection
-     * in two different ways, as a {@code "Mercator (1SP)"} or a {@code "Mercator (2SP)"} projection,
-     * each having their own set of parameters. The {@link #STRICT} or {@link #BY_CONTRACT} modes
-     * shall consider two projections as equal only if their
+     * <div class="section">Application to coordinate reference systems</div>
+     * If the objects being compared are {@link org.opengis.referencing.crs.CoordinateReferenceSystem} instances,
+     * then only the properties relevant to the coordinate localization shall be compared.
+     * Metadata like the {@linkplain org.apache.sis.referencing.crs.AbstractCRS#getIdentifiers() identifiers}
+     * or the {@linkplain org.apache.sis.referencing.crs.AbstractCRS#getDomainOfValidity() domain of validity},
+     * which have no impact on the coordinates being calculated, shall be ignored.
+     *
+     * <div class="section">Application to coordinate operations</div>
+     * If the objects being compared are {@link org.opengis.referencing.operation.MathTransform} instances,
+     * then two transforms defined in a different way may be considered equivalent. For example it is possible
+     * to define a {@linkplain org.apache.sis.referencing.operation.projection.Mercator Mercator} projection in
+     * two different ways, as a <cite>"Mercator (1SP)"</cite> or as a <cite>"Mercator (2SP)"</cite> projection,
+     * each having their own set of parameters.
+     * The {@link #STRICT} or {@link #BY_CONTRACT} modes shall consider two projections as equal only if their
      * {@linkplain org.apache.sis.referencing.operation.transform.AbstractMathTransform#getParameterValues()
      * parameter values} are strictly identical, while the {@code IGNORE_METADATA} mode can consider
      * those objects as equivalent despite difference in the set of parameters, as long as coordinate
-     * transformations still produce the same results.</p>
+     * transformations still produce the same results.
      *
      * <div class="note"><b>Example:</b> A <cite>"Mercator (2SP)"</cite> projection with a <cite>standard parallel</cite>
      * value of 60° produces the same results than a <cite>"Mercator (1SP)"</cite> projection with a <cite>scale factor</cite>
@@ -125,17 +124,37 @@ public enum ComparisonMode {
      * Only the attributes relevant to the object functionality are compared, with some tolerance
      * threshold on numerical values.
      *
-     * <div class="section">Application to coordinate transforms</div>
-     * If two {@link org.opengis.referencing.operation.MathTransform} objects are considered equal
-     * according this mode, then for any given identical source position, the two compared transforms
-     * shall compute at least approximatively the same target position. A small difference is
-     * tolerated between the target coordinates calculated by the two math transforms. How small
-     * is "small" is implementation dependent - the threshold can not be specified in the current
+     * <div class="section">Application to coordinate operations</div>
+     * If two {@link org.opengis.referencing.operation.MathTransform} objects are considered equal according this mode,
+     * then for any given identical source position, the two compared transforms shall compute at least approximatively
+     * the same target position.
+     * A small difference is tolerated between the target coordinates calculated by the two math transforms.
+     * How small is “small” is implementation dependent — the threshold can not be specified in the current
      * implementation, because of the non-linear nature of map projections.
      */
     APPROXIMATIVE,
 
     /**
+     * Most but not all attributes relevant to the object functionality are compared.
+     * This comparison mode is equivalent to {@link #APPROXIMATIVE}, except that it
+     * ignores some attributes that may differ between objects not equal but related.
+     *
+     * <p>The main purpose of this method is to verify if two Coordinate Reference Systems (CRS)
+     * are approximatively equal ignoring axis order.</p>
+     *
+     * <div class="note"><b>Example:</b>
+     * consider two geographic coordinate reference systems with the same attributes except axis order,
+     * where one CRS uses (<var>latitude</var>, <var>longitude</var>) axes
+     * and the other CRS uses (<var>longitude</var>, <var>latitude</var>) axes.
+     * All comparison modes (even {@code APPROXIMATIVE}) will consider those two CRS as different,
+     * except this {@code ALLOW_VARIANT} mode which will consider one CRS to be a variant of the other.
+     * </div>
+     *
+     * @since 0.7
+     */
+    ALLOW_VARIANT,
+
+    /**
      * Same as {@link #APPROXIMATIVE}, except that an {@link AssertionError} is thrown if the two
      * objects are not equal and assertions are enabled. The exception message and stack trace help
      * to locate which attributes are not equal. This mode is typically used in assertions like below:
@@ -178,14 +197,15 @@ public enum ComparisonMode {
     }
 
     /**
-     * If the two given objects are equals according one of the modes enumerated in this class,
-     * then returns that mode. Otherwise returns {@code null}. This method is used mostly for
-     * diagnostic purpose.
+     * If the two given objects are equal according one of the modes enumerated in this class,
+     * then returns that mode. Otherwise returns {@code null}.
+     *
+     * <p><b>Note:</b> this method never return the {@link #DEBUG} mode.</p>
      *
      * @param  o1 The first object to compare, or {@code null}.
      * @param  o2 The second object to compare, or {@code null}.
-     * @return The must suitable comparison mode, or {@code null} if the two given objects
-     *         are not equal for any mode in this enumeration.
+     * @return The most suitable comparison mode, or {@code null} if the two given objects
+     *         are not equal according any mode in this enumeration.
      */
     public static ComparisonMode equalityLevel(final Object o1, Object o2) {
         if (o1 == o2) {
@@ -207,6 +227,7 @@ public enum ComparisonMode {
             if (cp.equals(o2, BY_CONTRACT))     return BY_CONTRACT;
             if (cp.equals(o2, IGNORE_METADATA)) return IGNORE_METADATA;
             if (cp.equals(o2, APPROXIMATIVE))   return APPROXIMATIVE;
+            if (cp.equals(o2, ALLOW_VARIANT))   return ALLOW_VARIANT;
         }
         return null;
     }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Disposable.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Disposable.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Disposable.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Disposable.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -18,18 +18,31 @@ package org.apache.sis.util;
 
 
 /**
- * A resource that can be disposed when waiting for the garbage collector would be overly
- * conservative. Invoking the {@link #dispose()} method allows any resources held by this
- * object to be released. The result of calling any other method subsequent to a call to
- * this method is undefined.
+ * A resource that can be disposed when waiting for the garbage collector would be overly conservative.
+ * Invoking the {@link #dispose()} method allows any resources held by this object to be released.
+ * The result of calling any other method subsequent to a call to this method is undefined.
+ *
+ * <p>Data integrity shall not depend on {@code dispose()} method invocation.
+ * If some data may need to be {@linkplain java.io.OutputStream#flush() flushed to a stream}
+ * or {@linkplain java.sql.Connection#commit() committed to a database},
+ * then a {@code close()} method should be used instead.</p>
  *
  * <div class="section">Relationship with {@code Closeable}</div>
- * Some SIS classes may implement both the {@code Disposeable} and {@link java.io.Closeable}
- * interfaces. While very similar, those two interfaces serve slightly different purposes.
- * The {@code Closeable} interface closes a stream or a connection, but some classes can be
- * reused with a different stream. For example an {@link javax.imageio.ImageReader} can be
- * instantiated once and reused many time for reading different image streams of the same
- * format. However once an object has been disposed, it can not be used anymore.
+ * Some classes may implement both the {@code Disposeable} and {@link java.io.Closeable} interfaces.
+ * While very similar, those two interfaces serve slightly different purposes. The {@code Closeable}
+ * interface closes a stream or a connection, but some classes allow the object to be reused with a
+ * different stream. However once an object has been disposed, it can not be used anymore.
+ *
+ * <div class="note"><b>Example:</b>
+ * {@link javax.imageio.ImageReader} and {@link javax.imageio.ImageWriter} allow to reuse the same instance
+ * many times for reading or writing different images in the same format. New streams can be created, given
+ * to the {@code ImageReader} or {@code ImageWriter} and closed many times as long as {@code dispose()} has
+ * not been invoked.</div>
+ *
+ * Another difference is that {@link #dispose()} does not throw any checked exception.
+ * That method may be invoked in a background thread performing cleanup tasks,
+ * which would not know what to do in case of failure.
+ * Error during {@code dispose()} execution should not result in any lost of data.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Localized.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Localized.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Localized.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Localized.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -35,7 +35,7 @@ public interface Localized {
      * implementation-dependent, but typical interpretations are:
      *
      * <ul>
-     *   <li>A synonymous of the {@linkplain Locale#getDefault() system default locale};</li>
+     *   <li>A synonymous of the {@linkplain Locale#getDefault() system default locale}.</li>
      *   <li>A synonymous of {@link Locale#ROOT} for an "unlocalized" service. For example the
      *       service may format numbers using {@link Double#toString(double)} instead than
      *       {@link java.text.NumberFormat}.</li>
@@ -45,8 +45,6 @@ public interface Localized {
      * Nevertheless client codes should be prepared to receive null values.
      *
      * @return The locale, or {@code null} if not explicitly defined.
-     *
-     * @see org.apache.sis.io.CompoundFormat#getLocale()
      */
     Locale getLocale();
 }

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -32,10 +32,9 @@ import org.apache.sis.util.Disposable;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.system.DelayedRunnable;
+import org.apache.sis.internal.system.DelayedExecutor;
 import org.apache.sis.internal.system.ReferenceQueueConsumer;
 
-import static org.apache.sis.internal.system.DelayedExecutor.executeDaemonTask;
-
 // Branch-dependent imports
 import org.apache.sis.internal.jdk8.Supplier;
 
@@ -306,7 +305,7 @@ public class Cache<K,V> extends Abstract
         final Object previous;
         if (value != null) {
             previous = map.put(key, value);
-            executeDaemonTask(new Strong(key, value));
+            DelayedExecutor.schedule(new Strong(key, value));
         } else {
             previous = map.remove(key);
         }
@@ -385,8 +384,8 @@ public class Cache<K,V> extends Abstract
             final Reference<V> ref = (Reference<V>) value;
             final V result = ref.get();
             if (result != null && map.replace(key, ref, result)) {
-                ref.clear(); // Prevents the reference from being enqueued.
-                executeDaemonTask(new Strong(key, result));
+                ref.clear();                        // Prevents the reference from being enqueued.
+                DelayedExecutor.schedule(new Strong(key, result));
             }
             return result;
         }
@@ -478,8 +477,8 @@ public class Cache<K,V> extends Abstract
                      * would be useless.
                      */
                     if (map.replace(key, ref, result)) {
-                        ref.clear(); // Prevents the reference from being enqueued.
-                        executeDaemonTask(new Strong(key, result));
+                        ref.clear();                        // Prevents the reference from being enqueued.
+                        DelayedExecutor.schedule(new Strong(key, result));
                     }
                     return new Simple<V>(result);
                 }
@@ -712,7 +711,7 @@ public class Cache<K,V> extends Abstract
                 lock.unlock();
             }
             if (done) {
-                executeDaemonTask(this);
+                DelayedExecutor.schedule(this);
             }
         }
 

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -45,9 +45,9 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * {@preformat java
  *     public class CityLocation {
- *         public static final TableColumn<String> CITY_NAME  = new TableColumn<>(String.class);
- *         public static final TableColumn<Float>  LATITUDE   = new TableColumn<>(Float .class);
- *         public static final TableColumn<Float>  LONGTITUDE = new TableColumn<>(Float .class);
+ *         public static final TableColumn<String> CITY_NAME  = new TableColumn<>(String.class, "City name");
+ *         public static final TableColumn<Float>  LATITUDE   = new TableColumn<>(Float.class,  "Latitude");
+ *         public static final TableColumn<Float>  LONGTITUDE = new TableColumn<>(Float.class,  "Longitude");
  *
  *         public TreeTable createTable() {
  *             DefaultTreeTable table = new DefaultTreeTable(CITY_NAME, LATITUDE, LONGITUDE);

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java [UTF-8] Wed Jan 13 23:59:38 2016
@@ -30,6 +30,9 @@ import java.text.ParseException;
 import java.util.regex.Matcher;
 import org.opengis.util.CodeList;
 import java.nio.charset.Charset;
+import org.opengis.util.Type;
+import org.opengis.util.Record;
+import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
 import org.apache.sis.io.LineAppender;
 import org.apache.sis.io.TableAppender;
@@ -94,7 +97,7 @@ import static org.apache.sis.util.Charac
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.7
  * @module
  */
 public class TreeTableFormat extends TabularFormat<TreeTable> {
@@ -595,6 +598,12 @@ public class TreeTableFormat extends Tab
         private final Map<Object,Object> parentObjects;
 
         /**
+         * The format for the column in process of being written. This is a format to use for the column as a whole.
+         * This field is updated for every new column to write. May be {@code null} if the format is unspecified.
+         */
+        private transient Format columnFormat;
+
+        /**
          * Creates a new instance which will write to the given appendable.
          *
          * @param out           Where to format the tree.
@@ -613,21 +622,42 @@ public class TreeTableFormat extends Tab
         }
 
         /**
+         * Localizes the given name in the display locale, or returns "(Unnamed)" if no localized value is found.
+         */
+        private String toString(final GenericName name) {
+            final Locale locale = getDisplayLocale();
+            if (name != null) {
+                final InternationalString i18n = name.toInternationalString();
+                if (i18n != null) {
+                    final String localized = i18n.toString(locale);
+                    if (localized != null) {
+                        return localized;
+                    }
+                }
+                final String localized = name.toString();
+                if (localized != null) {
+                    return localized;
+                }
+            }
+            return '(' + Vocabulary.getResources(locale).getString(Vocabulary.Keys.Unnamed) + ')';
+        }
+
+        /**
          * Appends a textual representation of the given value.
          *
-         * @param  format The format to use for the column as a whole, or {@code null} if unknown.
-         * @param  value  The value to format (may be {@code null}).
+         * @param  value     The value to format (may be {@code null}).
+         * @param  recursive {@code true} if this method is invoking itself for writing collection values.
          */
-        private void formatValue(Format format, final Object value) throws IOException {
+        private void formatValue(final Object value, final boolean recursive) throws IOException {
             final CharSequence text;
             if (value == null) {
                 text = " "; // String for missing value.
-            } else if (format != null) {
-                if (format instanceof CompoundFormat<?>) {
-                    formatValue((CompoundFormat<?>) format, value);
+            } else if (columnFormat != null) {
+                if (columnFormat instanceof CompoundFormat<?>) {
+                    formatValue((CompoundFormat<?>) columnFormat, value);
                     return;
                 }
-                text = format.format(value);
+                text = columnFormat.format(value);
             } else if (value instanceof InternationalString) {
                 text = ((InternationalString) value).toString(getDisplayLocale());
             } else if (value instanceof CharSequence) {
@@ -636,6 +666,8 @@ public class TreeTableFormat extends Tab
                 text = Types.getCodeTitle((CodeList<?>) value).toString(getDisplayLocale());
             } else if (value instanceof Enum<?>) {
                 text = CharSequences.upperCaseToSentence(((Enum<?>) value).name());
+            } else if (value instanceof Type) {
+                text = toString(((Type) value).getTypeName());
             } else if (value instanceof Locale) {
                 final Locale locale = getDisplayLocale();
                 text = (locale != Locale.ROOT) ? ((Locale) value).getDisplayName(locale) : value.toString();
@@ -645,20 +677,55 @@ public class TreeTableFormat extends Tab
             } else if (value instanceof Charset) {
                 final Locale locale = getDisplayLocale();
                 text = (locale != Locale.ROOT) ? ((Charset) value).displayName(locale) : ((Charset) value).name();
+            } else if (value instanceof Record) {
+                formatCollection(((Record) value).getAttributes().values(), recursive);
+                return;
+            } else if (value instanceof Iterable<?>) {
+                formatCollection((Iterable<?>) value, recursive);
+                return;
+            } else if (value instanceof Object[]) {
+                formatCollection(Arrays.asList((Object[]) value), recursive);
+                return;
             } else {
                 /*
-                 * Check for a value-by-value format only as last resort.
-                 * If a column-wide format was given in argument to this method,
-                 * that format should have been used by above code in order to
-                 * produce a more uniform formatting.
+                 * Check for a value-by-value format only as last resort. If a column-wide format was specified by
+                 * the 'columnFormat' field, that format should have been used by above code in order to produce a
+                 * more uniform formatting.
                  */
-                format = getFormat(value.getClass());
+                final Format format = getFormat(value.getClass());
                 text = (format != null) ? format.format(value) : value.toString();
             }
             append(text);
         }
 
         /**
+         * Writes the values of the given collection. A maximum of 10 values will be written.
+         * If the collection contains other collections, the other collections will <strong>not</strong>
+         * be written recursively.
+         */
+        private void formatCollection(final Iterable<?> values, final boolean recursive)
+                throws IOException
+        {
+            if (values != null) {
+                if (recursive) {
+                    append('…');                                // Do not format collections inside collections.
+                } else {
+                    int count = 0;
+                    for (final Object value : values) {
+                        if (value != null) {
+                            if (count != 0) append(", ");
+                            formatValue(value, true);
+                            if (++count == 10) {                // Arbitrary limit.
+                                append(", …");
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
          * Work around for the inability to define the variable {@code <V>} locally.
          */
         @Workaround(library="JDK", version="1.7")
@@ -690,7 +757,8 @@ public class TreeTableFormat extends Tab
                 if (i != 0) {
                     writeColumnSeparator(out);
                 }
-                formatValue(formats[i], values[i]);
+                columnFormat = formats[i];
+                formatValue(values[i], false);
                 clear();
             }
             out.append(lineSeparator);




Mime
View raw message