sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1724528 [11/15] - in /sis/branches/JDK6: ./ 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...
Date Wed, 13 Jan 2016 23:25:42 GMT
Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] Wed Jan 13 23:25: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/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java [UTF-8] Wed Jan 13 23:25: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/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/setup/About.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/setup/About.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/setup/About.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/setup/About.java [UTF-8] Wed Jan 13 23:25: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/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] Wed Jan 13 23:25: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/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java [UTF-8] Wed Jan 13 23:25: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/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/Disposable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/Disposable.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/Disposable.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/Disposable.java [UTF-8] Wed Jan 13 23:25: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/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/Localized.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/Localized.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/Localized.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/Localized.java [UTF-8] Wed Jan 13 23:25: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/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java [UTF-8] Wed Jan 13 23:25: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/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java [UTF-8] Wed Jan 13 23:25: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/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java [UTF-8] Wed Jan 13 23:25:38 2016
@@ -29,6 +29,9 @@ import java.text.ParsePosition;
 import java.text.ParseException;
 import java.util.regex.Matcher;
 import java.nio.charset.Charset;
+import org.opengis.util.Type;
+import org.opengis.util.Record;
+import org.opengis.util.GenericName;
 import org.opengis.util.ControlledVocabulary;
 import org.opengis.util.InternationalString;
 import org.apache.sis.io.LineAppender;
@@ -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((ControlledVocabulary) 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);

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakValueHashMap.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakValueHashMap.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakValueHashMap.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/collection/WeakValueHashMap.java [UTF-8] Wed Jan 13 23:25:38 2016
@@ -80,7 +80,7 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  *
  * @see java.util.WeakHashMap
@@ -398,7 +398,7 @@ public class WeakValueHashMap<K,V> exten
      * Implementation of {@link #put(Object, Object)} and {@link #remove(Object)} operations
      */
     @SuppressWarnings("unchecked")
-    private synchronized V intern(final Object key, final V value) {
+    private synchronized V intern(final Object key, final V value, final boolean replace) {
         assert isValid();
         /*
          * If 'value' is already contained in this WeakValueHashMap, we need to clear it.
@@ -410,6 +410,9 @@ public class WeakValueHashMap<K,V> exten
         for (Entry e = table[index]; e != null; e = (Entry) e.next) {
             if (keyEquals(key, e.key)) {
                 oldValue = e.get();
+                if (oldValue != null && !replace) {
+                    return oldValue;
+                }
                 e.dispose();
                 table = this.table; // May have changed.
                 index = hash % table.length;
@@ -435,8 +438,7 @@ public class WeakValueHashMap<K,V> exten
      *
      * @param  key key with which the specified value is to be associated.
      * @param  value value to be associated with the specified key.
-     * @return The previous value associated with specified key, or {@code null}
-     *         if there was no mapping for key.
+     * @return The previous value associated with specified key, or {@code null} if there was no mapping for key.
      *
      * @throws NullArgumentException if the key or the value is {@code null}.
      */
@@ -446,19 +448,40 @@ public class WeakValueHashMap<K,V> exten
             throw new NullArgumentException(Errors.format(key == null
                     ? Errors.Keys.NullMapKey : Errors.Keys.NullMapValue));
         }
-        return intern(key, value);
+        return intern(key, value, true);
+    }
+
+    /**
+     * Associates the specified value with the specified key in this map if no value were previously associated.
+     * If an other value is already associated to the given key, then the map is left unchanged and the current
+     * value is returned. Otherwise the specified value is associated to the key using a {@link WeakReference}
+     * and {@code null} is returned.
+     *
+     * @param  key key with which the specified value is to be associated.
+     * @param  value value to be associated with the specified key.
+     * @return The current value associated with specified key, or {@code null} if there was no mapping for key.
+     *
+     * @throws NullArgumentException if the key or the value is {@code null}.
+     *
+     * @since 0.7
+     */
+    public V putIfAbsent(final K key, final V value) throws NullArgumentException {
+        if (key == null || value == null) {
+            throw new NullArgumentException(Errors.format(key == null
+                    ? Errors.Keys.NullMapKey : Errors.Keys.NullMapValue));
+        }
+        return intern(key, value, false);
     }
 
     /**
      * Removes the mapping for this key from this map if present.
      *
      * @param key key whose mapping is to be removed from the map.
-     * @return previous value associated with specified key, or {@code null}
-     *         if there was no entry for key.
+     * @return previous value associated with specified key, or {@code null} if there was no entry for key.
      */
     @Override
     public V remove(final Object key) {
-        return intern(key, null);
+        return intern(key, null, true);
     }
 
     /**
@@ -477,6 +500,7 @@ public class WeakValueHashMap<K,V> exten
      * @return a set view of the mappings contained in this map.
      */
     @Override
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     public synchronized Set<Map.Entry<K,V>> entrySet() {
         if (entrySet == null) {
             entrySet = new EntrySet();

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameSpace.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameSpace.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameSpace.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameSpace.java [UTF-8] Wed Jan 13 23:25:38 2016
@@ -209,9 +209,7 @@ public class DefaultNameSpace implements
      *          parsed names} of any name in that namespace.
      * @return A namespace having the given name, or {@code null} if name was null.
      */
-    static DefaultNameSpace forName(final GenericName name,
-            final String headSeparator, final String separator)
-    {
+    static DefaultNameSpace forName(final GenericName name, final String headSeparator, final String separator) {
         if (name == null) {
             return null;
         }
@@ -251,7 +249,7 @@ public class DefaultNameSpace implements
      */
     @Override
     public boolean isGlobal() {
-        return false; // To be overridden by GlobalNameSpace.
+        return false;               // To be overridden by GlobalNameSpace.
     }
 
     /**
@@ -388,7 +386,7 @@ public class DefaultNameSpace implements
         if (name == null) {
             name = key;
         }
-        final WeakValueHashMap<String,Object> childs = this.childs; // Paranoiac protection against accidental changes.
+        final WeakValueHashMap<String,Object> childs = this.childs;     // Paranoiac protection against accidental changes.
         DefaultNameSpace child;
         synchronized (childs) {
             final Object existing = childs.get(key);
@@ -396,7 +394,7 @@ public class DefaultNameSpace implements
                 child = (DefaultNameSpace) existing;
                 if (!child.separator    .equals(separator) ||
                     !child.headSeparator.equals(headSeparator) ||
-                    !child.name         .equals(name)) // Same test than equalsIgnoreParent.
+                    !child.name         .equals(name))                  // Same test than equalsIgnoreParent.
                 {
                     child = new DefaultNameSpace(this, name, headSeparator, separator);
                     /*
@@ -408,7 +406,7 @@ public class DefaultNameSpace implements
             } else {
                 child = new DefaultNameSpace(this, name, headSeparator, separator);
                 if (childs.put(key, child) != existing) {
-                    throw new AssertionError(); // Paranoiac check.
+                    throw new AssertionError();                         // Paranoiac check.
                 }
             }
         }
@@ -429,7 +427,7 @@ public class DefaultNameSpace implements
     final DefaultLocalName local(final CharSequence name, final DefaultLocalName candidate) {
         ensureNonNull("name", name);
         final String key = name.toString();
-        final WeakValueHashMap<String,Object> childs = this.childs; // Paranoiac protection against accidental changes.
+        final WeakValueHashMap<String,Object> childs = this.childs;     // Paranoiac protection against accidental changes.
         DefaultLocalName child;
         synchronized (childs) {
             final Object existing = childs.get(key);
@@ -448,7 +446,7 @@ public class DefaultNameSpace implements
             // Cache only if the slot is not already occupied by a NameSpace.
             if (!(existing instanceof DefaultNameSpace)) {
                 if (childs.put(key, child) != existing) {
-                    throw new AssertionError(); // Paranoiac check.
+                    throw new AssertionError();                         // Paranoiac check.
                 }
             }
         }
@@ -510,7 +508,7 @@ public class DefaultNameSpace implements
     private boolean equalsIgnoreParent(final DefaultNameSpace that) {
         return Objects.equals(this.headSeparator, that.headSeparator) &&
                Objects.equals(this.separator,     that.separator) &&
-               Objects.equals(this.name,          that.name); // Most expensive test last.
+               Objects.equals(this.name,          that.name);               // Most expensive test last.
     }
 
     /**
@@ -546,7 +544,7 @@ public class DefaultNameSpace implements
             } else {
                 init();
                 if (pool.put(key, this) != existing) {
-                    throw new AssertionError(); // Paranoiac check.
+                    throw new AssertionError();             // Paranoiac check.
                 }
                 return this;
             }

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecord.java [UTF-8] Wed Jan 13 23:25:38 2016
@@ -108,7 +108,7 @@ public class DefaultRecord implements Re
 
     /**
      * Returns the dictionary of all (<var>name</var>, <var>value</var>) pairs in this record.
-     * This method returns a view which will delegate all {@code get} and {@code pt} operations to
+     * This method returns a view which will delegate all {@code get} and {@code put} operations to
      * the {@link #locate(MemberName)} and {@link #set(MemberName, Object)} methods respectively.
      *
      * @return The dictionary of all (<var>name</var>, <var>value</var>) pairs in this record.

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecordSchema.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecordSchema.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecordSchema.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultRecordSchema.java [UTF-8] Wed Jan 13 23:25:38 2016
@@ -29,6 +29,7 @@ import org.opengis.util.NameFactory;
 import org.opengis.util.NameSpace;
 import org.opengis.util.RecordSchema;
 import org.opengis.util.RecordType;
+import org.opengis.feature.AttributeType;
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ObjectConverter;
@@ -184,10 +185,10 @@ public class DefaultRecordSchema impleme
             final Map.Entry<CharSequence,Class<?>> e1 = it1.next();
             final Map.Entry<MemberName,Type> e2 = it2.next();
             if (!e2.getKey().tip().toString().equals(e1.toString())) {
-                break; // Member names differ.
+                break;      // Member names differ.
             }
-            if (!((SimpleAttributeType) e2.getValue()).getValueClass().equals(e1.getValue())) {
-                break; // Value classes differ.
+            if (!((AttributeType) e2.getValue()).getValueClass().equals(e1.getValue())) {
+                break;      // Value classes differ.
             }
         }
         throw new IllegalArgumentException(Errors.format(Errors.Keys.RecordAlreadyDefined_2, getSchemaName(), typeName));
@@ -219,7 +220,7 @@ public class DefaultRecordSchema impleme
             }
             type = new SimpleAttributeType(name, valueClass);
             final Type old = attributeTypes.putIfAbsent(valueClass, type);
-            if (old != null) { // May happen if the type has been computed concurrently.
+            if (old != null) {      // May happen if the type has been computed concurrently.
                 return old;
             }
         }

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/logging/MonolineFormatter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/logging/MonolineFormatter.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/logging/MonolineFormatter.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/logging/MonolineFormatter.java [UTF-8] Wed Jan 13 23:25:38 2016
@@ -54,7 +54,7 @@ import org.apache.sis.internal.jdk7.JDK7
  * <tr><td><code>00:01</code></td><td style="background:blue"><code>CONFIG</code></td>
  *     <td><code><b>[MyApplication]</b> Read configuration from “my-application/setup.xml”.</code></td></tr>
  * <tr><td><code>00:03</code></td><td style="background:green"><code>INFO</code></td>
- *     <td><code><b>[DirectEpsgFactory]</b> Connected to the EPSG database version 6.9 on JavaDB 10.8.</code></td></tr>
+ *     <td><code><b>[EPSGFactory]</b> Connected to the EPSG database version 6.9 on JavaDB 10.8.</code></td></tr>
  * <tr><td><code>00:12</code></td><td style="background:goldenrod"><code>WARNING</code></td>
  *     <td><code><b>[DefaultTemporalExtent]</b> This operation requires the “sis-temporal” module.</code></td></tr>
  * </table></blockquote>

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Wed Jan 13 23:25:38 2016
@@ -151,6 +151,16 @@ public final class Errors extends Indexe
         public static final short CanNotRepresentInFormat_2 = 10;
 
         /**
+         * Target dimension {0} depends on excluded source dimensions.
+         */
+        public static final short CanNotSeparateTargetDimension_1 = 175;
+
+        /**
+         * Can not set a value for parameter “{0}”.
+         */
+        public static final short CanNotSetParameterValue_1 = 214;
+
+        /**
          * Can not set a value for property “{0}”.
          */
         public static final short CanNotSetPropertyValue_1 = 11;
@@ -186,6 +196,16 @@ public final class Errors extends Indexe
         public static final short ColinearAxisDirections_2 = 14;
 
         /**
+         * Database error while creating a ‘{0}’ object for code “{1}”.
+         */
+        public static final short DatabaseError_2 = 209;
+
+        /**
+         * Origin of temporal datum shall be a date.
+         */
+        public static final short DatumOriginShallBeDate = 213;
+
+        /**
          * Thread “{0}” is dead.
          */
         public static final short DeadThread_1 = 15;
@@ -276,6 +296,11 @@ public final class Errors extends Indexe
         public static final short ExcessiveStringSize = 153;
 
         /**
+         * No factory of kind ‘{0}’ found.
+         */
+        public static final short FactoryNotFound_1 = 205;
+
+        /**
          * File “{0}” has not been found.
          */
         public static final short FileNotFound_1 = 166;
@@ -358,6 +383,11 @@ public final class Errors extends Indexe
         public static final short IllegalFormatPatternForClass_2 = 35;
 
         /**
+         * “{1}” is not a valid identifier for the “{0}” code space.
+         */
+        public static final short IllegalIdentifierForCodespace_2 = 208;
+
+        /**
          * The “{0}” language is not recognized.
          */
         public static final short IllegalLanguageCode_1 = 36;
@@ -479,11 +509,6 @@ public final class Errors extends Indexe
         public static final short InfiniteArgumentValue_1 = 51;
 
         /**
-         * Inseparable transform.
-         */
-        public static final short InseparableTransform = 175;
-
-        /**
          * Argument ‘{0}’ shall contain at least {1} elements. A number of {2} is insufficient.
          */
         public static final short InsufficientArgumentSize_3 = 53;
@@ -524,6 +549,11 @@ public final class Errors extends Indexe
         public static final short MismatchedDimension_3 = 59;
 
         /**
+         * The grid geometry must be the same for “{0}” and “{1}”.
+         */
+        public static final short MismatchedGridGeometry_2 = 203;
+
+        /**
          * Mismatched matrix sizes: expected {0}×{1} but got {2}×{3}.
          */
         public static final short MismatchedMatrixSize_4 = 60;
@@ -811,6 +841,11 @@ public final class Errors extends Indexe
         public static final short NullMapValue = 97;
 
         /**
+         * Unexpected null value in record “{2}” for the column “{1}” in table “{0}”.
+         */
+        public static final short NullValueInTable_3 = 207;
+
+        /**
          * Array length is {0}, while we expected an even length.
          */
         public static final short OddArrayLength_1 = 98;
@@ -836,6 +871,11 @@ public final class Errors extends Indexe
         public static final short RecordAlreadyDefined_2 = 161;
 
         /**
+         * Recursive call while creating an object of type ‘{0}’ for code “{1}”.
+         */
+        public static final short RecursiveCreateCallForCode_2 = 210;
+
+        /**
          * Recursive call while creating an object for the “{0}” key.
          */
         public static final short RecursiveCreateCallForKey_1 = 99;
@@ -861,6 +901,11 @@ public final class Errors extends Indexe
         public static final short StreamIsForwardOnly_1 = 103;
 
         /**
+         * Table “{0}” has not been found.
+         */
+        public static final short TableNotFound_1 = 206;
+
+        /**
          * Expected at least {0} argument{0,choice,1#|2#s}, but got {1}.
          */
         public static final short TooFewArguments_2 = 104;
@@ -906,6 +951,11 @@ public final class Errors extends Indexe
         public static final short UnexpectedCharactersAfter_2 = 198;
 
         /**
+         * Unexpected dimension for a coordinate system of type ‘{0}’.
+         */
+        public static final short UnexpectedDimensionForCS_1 = 212;
+
+        /**
          * Unexpected end of file while reading “{0}”.
          */
         public static final short UnexpectedEndOfFile_1 = 109;
@@ -986,6 +1036,11 @@ public final class Errors extends Indexe
         public static final short UnknownType_1 = 118;
 
         /**
+         * Unit “{0}” is not recognized.
+         */
+        public static final short UnknownUnit_1 = 211;
+
+        /**
          * This affine transform is unmodifiable.
          */
         public static final short UnmodifiableAffineTransform = 119;
@@ -1036,6 +1091,11 @@ public final class Errors extends Indexe
         public static final short UnspecifiedCRS = 173;
 
         /**
+         * Dimensions have not been specified.
+         */
+        public static final short UnspecifiedDimensions = 204;
+
+        /**
          * No format is specified for objects of class ‘{0}’.
          */
         public static final short UnspecifiedFormatForClass_1 = 126;
@@ -1051,6 +1111,11 @@ public final class Errors extends Indexe
         public static final short UnsupportedImplementation_1 = 127;
 
         /**
+         * The “{0}” interpolation is unsupported.
+         */
+        public static final short UnsupportedInterpolation_1 = 202;
+
+        /**
          * The ‘{0}’ operation is unsupported.
          */
         public static final short UnsupportedOperation_1 = 128;

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1724528&r1=1724527&r2=1724528&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Wed Jan 13 23:25:38 2016
@@ -41,6 +41,8 @@ CanNotOpen_1                      = Can
 CanNotParseFile_2                 = Can not parse \u201c{1}\u201d as a file in the {0} format.
 CanNotRead_1                      = Can not read \u201c{0}\u201d.
 CanNotRepresentInFormat_2         = Can not represent \u201c{1}\u201d in the {0} format.
+CanNotSeparateTargetDimension_1   = Target dimension {0} depends on excluded source dimensions.
+CanNotSetParameterValue_1         = Can not set a value for parameter \u201c{0}\u201d.
 CanNotSetPropertyValue_1          = Can not set a value for property \u201c{0}\u201d.
 CanNotTransformEnvelope           = Can not transform envelope.
 CanNotTransformEnvelopeToGeodetic = Can not transform envelope to a geodetic CRS.
@@ -48,6 +50,8 @@ CircularReference                 = Circ
 ClassNotFinal_1                   = Class \u2018{0}\u2019 is not final.
 CloneNotSupported_1               = Can not clone an object of type \u2018{0}\u2019.
 ColinearAxisDirections_2          = Axis directions {0} and {1} are colinear.
+DatabaseError_2                   = Database error while creating a \u2018{0}\u2019 object for code \u201c{1}\u201d.
+DatumOriginShallBeDate            = Origin of temporal datum shall be a date.
 DeadThread_1                      = Thread \u201c{0}\u201d is dead.
 DirectoryNotExpected_1            = The \u201c{0}\u201d file points to a directory instead of a regular file.
 DuplicatedElement_1               = Element \u201c{0}\u201d is duplicated.
@@ -66,6 +70,7 @@ ExcessiveArgumentSize_3           = Argu
 ExcessiveListSize_2               = A size of {1} elements is excessive for the \u201c{0}\u201d list.
 ExcessiveNumberOfDimensions_1     = For this algorithm, {0} is an excessive number of dimensions.
 ExcessiveStringSize               = The character string is too long.
+FactoryNotFound_1                 = No factory of kind \u2018{0}\u2019 found.
 FileNotFound_1                    = File \u201c{0}\u201d has not been found.
 ForbiddenAttribute_2              = Attribute \u201c{0}\u201d is not allowed for an object of type \u2018{1}\u2019.
 ForbiddenProperty_1               = Property \u201c{0}\u201d is not allowed.
@@ -81,6 +86,7 @@ IllegalClass_2                    = Clas
 IllegalCoordinateSystem_1         = Coordinate system can not be \u201c{0}\u201d.
 IllegalCRSType_1                  = Coordinate reference system can not be of type \u2018{0}\u2019.
 IllegalFormatPatternForClass_2    = The \u201c{1}\u201d pattern can not be applied to formating of objects of type \u2018{0}\u2019.
+IllegalIdentifierForCodespace_2   = \u201c{1}\u201d is not a valid identifier for the \u201c{0}\u201d code space.
 IllegalLanguageCode_1             = The \u201c{0}\u201d language is not recognized.
 IllegalMemberType_2               = Member \u201c{0}\u201d can not be associated to type \u201c{1}\u201d.
 IllegalOperationDimension_3       = Dimensions of \u201c{0}\u201d operation can not be ({1} \u2192 {2}).
@@ -106,7 +112,6 @@ IdentifierAlreadyBound_1          = Iden
 IndexOutOfBounds_1                = Index {0} is out of bounds.
 IndicesOutOfBounds_2              = Indices ({0}, {1}) are out of bounds.
 InfiniteArgumentValue_1           = Argument \u2018{0}\u2019 can not take an infinite value.
-InseparableTransform              = Inseparable transform.
 InsufficientArgumentSize_3        = Argument \u2018{0}\u2019 shall contain at least {1} elements. A number of {2} is insufficient.
 KeyCollision_1                    = A different value is already associated to the \u201c{0}\u201d key.
 LatitudesAreOpposite_2            = Latitudes {0} and {1} are opposite.
@@ -115,6 +120,7 @@ MismatchedArrayLengths            = Mism
 MismatchedCRS                     = The coordinate reference system must be the same for all objects.
 MismatchedDimension_2             = Mismatched object dimensions: {0}D and {1}D.
 MismatchedDimension_3             = Argument \u2018{0}\u2019 has {2} dimension{2,choice,1#|2#s}, while {1} was expected.
+MismatchedGridGeometry_2          = The grid geometry must be the same for \u201c{0}\u201d and \u201c{1}\u201d.
 MismatchedMatrixSize_4            = Mismatched matrix sizes: expected {0}\u00d7{1} but got {2}\u00d7{3}.
 MismatchedParameterDescriptor_1   = Mismatched descriptor for \u201c{0}\u201d parameter.
 MismatchedPropertyType_1          = Mismatched type for \u201c{0}\u201d property.
@@ -173,16 +179,19 @@ NullCollectionElement_1           = \u20
 # Use the OGC/ISO "Dictionary" word instead of "Map" for avoiding confusion with geographic map.
 NullMapKey                        = Null key is not allowed in this dictionary.
 NullMapValue                      = Null values are not allowed in this dictionary.
+NullValueInTable_3                = Unexpected null value in record \u201c{2}\u201d for the column \u201c{1}\u201d in table \u201c{0}\u201d.
 OddArrayLength_1                  = Array length is {0}, while we expected an even length.
 PropertyAlreadyExists_2           = Property \u201c{1}\u201d already exists in \u201c{0}\u201d.
 ParameterNotFound_2               = No parameter named \u201c{1}\u201d has been found in \u201c{0}\u201d.
 PropertyNotFound_2                = No property named \u201c{1}\u201d has been found in \u201c{0}\u201d.
 RecordAlreadyDefined_2            = Record \u201c{1}\u201d is already defined in schema \u201c{0}\u201d.
 RecursiveCreateCallForKey_1       = Recursive call while creating an object for the \u201c{0}\u201d key.
+RecursiveCreateCallForCode_2      = Recursive call while creating an object of type \u2018{0}\u2019 for code \u201c{1}\u201d.
 RequireDecimalSeparator           = A decimal separator is required.
 SingularMatrix                    = Matrix is singular.
 StalledThread_1                   = Thread \u201c{0}\u201d seems stalled.
 StreamIsForwardOnly_1             = Can not move backward in the \u201c{0}\u201d stream.
+TableNotFound_1                   = Table \u201c{0}\u201d has not been found.
 TooFewArguments_2                 = Expected at least {0} argument{0,choice,1#|2#s}, but got {1}.
 TooFewOccurrences_2               = Too few occurrences of \u201c{1}\u201d. Expected at least {0} of them.
 TooManyArguments_2                = Expected at most {0} argument{0,choice,1#|2#s}, but got {1}.
@@ -192,6 +201,7 @@ UndefinedOrderingForElements_2    = Orde
 UnexpectedArrayLength_2           = Expected an array of length {0}, but got {1}.
 UnexpectedChange_1                = Unexpected change in \u2018{0}\u2019.
 UnexpectedCharactersAfter_2       = The \u201c{1}\u201d characters after \u201c{0}\u201d was unexpected.
+UnexpectedDimensionForCS_1        = Unexpected dimension for a coordinate system of type \u2018{0}\u2019.
 UnexpectedEndOfFile_1             = Unexpected end of file while reading \u201c{0}\u201d.
 UnexpectedEndOfString_1           = More characters were expected at the end of \u201c{0}\u201d.
 UnexpectedFileFormat_2            = File \u201c{1}\u201d seems to be encoded in an other format than {0}.
@@ -208,6 +218,7 @@ UnknownKeyword_1                  = Keyw
 UnknownOption_1                   = Option \u201c{0}\u201d is not recognized.
 UnknownType_1                     = Type \u2018{0}\u2019 is unknown in this context.
 UnknownTypeForProperty_1          = Type of the \u201c{0}\u201d property is unknown.
+UnknownUnit_1                     = Unit \u201c{0}\u201d is not recognized.
 UnmodifiableAffineTransform       = This affine transform is unmodifiable.
 UnmodifiableCellValue_2           = The cell at column \u201c{1}\u201d of row \u201c{0}\u201d is unmodifiable.
 UnmodifiableGeometry              = This geometry is not modifiable.
@@ -218,9 +229,11 @@ UnparsableStringForClass_3        = Text
 UnparsableStringInElement_2       = Can not parse \u201c{1}\u201d in element \u201c{0}\u201d.
 UnresolvedFeatureName_1           = Feature named \u201c{0}\u201d has not yet been resolved.
 UnspecifiedCRS                    = Coordinate reference system has not been specified.
+UnspecifiedDimensions             = Dimensions have not been specified.
 UnspecifiedFormatForClass_1       = No format is specified for objects of class \u2018{0}\u2019.
 UnspecifiedParameterValues        = Parameter values have not been specified.
 UnsupportedImplementation_1       = Can not handle instances of \u2018{0}\u2019 because arbitrary implementations are not yet supported.
+UnsupportedInterpolation_1        = The \u201c{0}\u201d interpolation is unsupported.
 UnsupportedOperation_1            = The \u2018{0}\u2019 operation is unsupported.
 UnsupportedType_1                 = The \u2018{0}\u2019 type is unsupported.
 UnsupportedVersion_1              = Version {0} is not supported.



Mime
View raw message