sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1415758 [1/3] - in /sis/trunk: ./ ide-project/NetBeans/ ide-project/NetBeans/nbproject/ sis-utility/src/main/java/org/apache/sis/internal/util/ sis-utility/src/main/java/org/apache/sis/io/ sis-utility/src/main/java/org/apache/sis/math/ sis...
Date Fri, 30 Nov 2012 17:38:20 GMT
Author: desruisseaux
Date: Fri Nov 30 17:38:17 2012
New Revision: 1415758

URL: http://svn.apache.org/viewvc?rev=1415758&view=rev
Log:
Merge from the JDK6 branch.

Added:
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/io/DefaultFormat.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/io/DefaultFormat.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/math/Statistics.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/math/Statistics.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/math/StatisticsFormat.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/math/StatisticsFormat.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/KeyConstants.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/KeyConstants.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/NilObject.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/xml/NilObject.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/NilObjectHandler.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/xml/NilObjectHandler.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/NilReason.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/xml/NilReason.java
    sis/trunk/sis-utility/src/main/resources/org/apache/sis/internal/
      - copied from r1415754, sis/branches/JDK6/sis-utility/src/main/resources/org/apache/sis/internal/
    sis/trunk/sis-utility/src/test/java/org/apache/sis/math/StatisticsTest.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/math/StatisticsTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/test/foreigner/
      - copied from r1415754, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/foreigner/
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/TableColumnTest.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/TableColumnTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/xml/NilReasonTest.java
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/xml/NilReasonTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/xml/readme.txt
      - copied unchanged from r1415754, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/xml/readme.txt
Removed:
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/ColumnConstant.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTables.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/StringColumn.java
Modified:
    sis/trunk/   (props changed)
    sis/trunk/ide-project/NetBeans/build.xml
    sis/trunk/ide-project/NetBeans/nbproject/project.properties
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/io/package-info.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Exceptions.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Locales.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Numbers.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/IndexedResourceBundle.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/ResourceInternationalString.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
    sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/util/X364Test.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/CacheTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/resources/IndexedResourceBundleTest.java
    sis/trunk/src/main/docbook/book.xsl
    sis/trunk/src/main/docbook/fr/XML.xml
    sis/trunk/src/main/docbook/fr/utility.xml
    sis/trunk/src/site/resources/book/book.css

Propchange: sis/trunk/
------------------------------------------------------------------------------
  Merged /sis/branches/JDK7:r1411574-1415739
  Merged /sis/branches/JDK6:r1411578-1415754

Modified: sis/trunk/ide-project/NetBeans/build.xml
URL: http://svn.apache.org/viewvc/sis/trunk/ide-project/NetBeans/build.xml?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/ide-project/NetBeans/build.xml (original)
+++ sis/trunk/ide-project/NetBeans/build.xml Fri Nov 30 17:38:17 2012
@@ -22,5 +22,12 @@
         <include name="*.utf"/>
       </fileset>
     </copy>
+
+    <!-- Following are classical properties resources files. -->
+    <copy todir="${build.classes.dir}/org/apache/sis/internal/util">
+      <fileset dir="${project.root}/sis-utility/src/main/resources/org/apache/sis/internal/util">
+        <include name="*.properties"/>
+      </fileset>
+    </copy>
   </target>
 </project>

Modified: sis/trunk/ide-project/NetBeans/nbproject/project.properties
URL: http://svn.apache.org/viewvc/sis/trunk/ide-project/NetBeans/nbproject/project.properties?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/ide-project/NetBeans/nbproject/project.properties (original)
+++ sis/trunk/ide-project/NetBeans/nbproject/project.properties Fri Nov 30 17:38:17 2012
@@ -18,7 +18,7 @@ source.encoding      = UTF-8
 javac.source         = 1.6
 javac.target         = 1.6
 platform.active      = default_platform
-run.jvmargs          = -ea
+run.jvmargs          = -ea -Dorg.apache.sis.test.verbose=true
 junit.forkmode       = once
 
 #

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Citations.java Fri Nov 30 17:38:17 2012
@@ -23,6 +23,8 @@ import org.opengis.metadata.citation.Cit
 import org.opengis.util.InternationalString;
 import org.apache.sis.util.Static;
 
+import static org.apache.sis.util.CharSequences.trimWhitespaces;
+
 
 /**
  * Utility methods working on {@link Citation} objects. The public facade of those methods is
@@ -79,13 +81,13 @@ public final class Citations extends Sta
             do {
                 if (candidate != null) {
                     // The "null" locale argument is required for getting the unlocalized version.
-                    final String asString = candidate.toString(null);
-                    if (titleMatches(c1, asString)) {
+                    final String unlocalized = candidate.toString(null);
+                    if (titleMatches(c1, unlocalized)) {
                         return true;
                     }
-                    final String asLocalized = candidate.toString();
-                    if (asLocalized != asString // Slight optimization for a common case.
-                            && titleMatches(c1, asLocalized))
+                    final String localized = candidate.toString();
+                    if (!Objects.equals(localized, unlocalized) // Slight optimization for a common case.
+                            && titleMatches(c1, localized))
                     {
                         return true;
                     }
@@ -114,19 +116,19 @@ public final class Citations extends Sta
      */
     public static boolean titleMatches(final Citation citation, String title) {
         if (citation != null && title != null) {
-            title = title.trim();
+            title = trimWhitespaces(title);
             InternationalString candidate = citation.getTitle();
             Iterator<? extends InternationalString> iterator = null;
             do {
                 if (candidate != null) {
                     // The "null" locale argument is required for getting the unlocalized version.
-                    final String asString = candidate.toString(null);
-                    if (asString != null && asString.trim().equalsIgnoreCase(title)) {
+                    final String unlocalized = trimWhitespaces(candidate.toString(null));
+                    if (unlocalized != null && unlocalized.equalsIgnoreCase(title)) {
                         return true;
                     }
-                    final String asLocalized = candidate.toString();
-                    if (asLocalized != asString // Slight optimization for a common case.
-                            && asLocalized != null && asLocalized.trim().equalsIgnoreCase(title))
+                    final String localized = trimWhitespaces(candidate).toString();
+                    if (localized != unlocalized // Slight optimization for a common case.
+                            && (localized != null) && localized.equalsIgnoreCase(title))
                     {
                         return true;
                     }
@@ -203,7 +205,7 @@ public final class Citations extends Sta
      */
     public static boolean identifierMatches(final Citation citation, String identifier) {
         if (citation != null && identifier != null) {
-            identifier = identifier.trim();
+            identifier = trimWhitespaces(identifier);
             final Iterator<? extends Identifier> identifiers = iterator(citation.getIdentifiers());
             if (identifiers == null) {
                 return titleMatches(citation, identifier);
@@ -212,7 +214,7 @@ public final class Citations extends Sta
                 final Identifier id = identifiers.next();
                 if (id != null) {
                     final String code = id.getCode();
-                    if (code != null && identifier.equalsIgnoreCase(code.trim())) {
+                    if (code != null && identifier.equalsIgnoreCase(trimWhitespaces(code))) {
                         return true;
                     }
                 }
@@ -237,9 +239,8 @@ public final class Citations extends Sta
             if (it != null) while (it.hasNext()) {
                 final Identifier id = it.next();
                 if (id != null) {
-                    String candidate = id.getCode();
+                    final String candidate = trimWhitespaces(id.getCode());
                     if (candidate != null) {
-                        candidate = candidate.trim();
                         final int length = candidate.length();
                         if (length != 0) {
                             if (identifier == null || length < identifier.length()) {

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java Fri Nov 30 17:38:17 2012
@@ -117,7 +117,7 @@ abstract class DaemonThread extends Thre
      * <p><strong>This method is for internal use by Apache SIS shutdown hooks only.</strong>
      * Users should never invoke this method explicitely.</p>
      *
-     * @param  first The first thread in the chain of threads to kill.
+     * @param  thread The first thread in the chain of threads to kill.
      * @param  stopWaitingAt A {@link System#nanoTime()} value telling when to stop waiting.
      *         This is used for preventing shutdown process to block an indefinite amount of time.
      * @throws InterruptedException If an other thread invoked {@link #interrupt()} while
@@ -125,15 +125,16 @@ abstract class DaemonThread extends Thre
      *
      * @see Threads#shutdown(long)
      */
-    static void killAll(final DaemonThread first, final long stopWaitingAt) throws InterruptedException {
-        for (DaemonThread thread=first; thread!=null; thread=thread.previous) {
-            thread.killRequested = true;
-            thread.interrupt();
+    static void killAll(DaemonThread thread, final long stopWaitingAt) throws InterruptedException {
+        for (DaemonThread t=thread; t!=null; t=t.previous) {
+            t.killRequested = true;
+            t.interrupt();
         }
-        for (DaemonThread thread=first; thread!=null; thread=thread.previous) {
+        while (thread != null) {
             final long delay = stopWaitingAt - System.nanoTime();
             if (delay <= 0) break;
             thread.join(delay / 1000000); // Convert nanoseconds to milliseconds.
+            thread = thread.previous;
         }
     }
 
@@ -142,18 +143,24 @@ abstract class DaemonThread extends Thre
      * always be null. A non-empty list would be a symptom for a severe problem, probably
      * requiring an application reboot.
      *
-     * @param  first The first thread in the chain of threads to verify.
+     * <p><strong>This method is for internal use by Apache SIS only.</strong>
+     * Users should never invoke this method explicitely.</p>
+     *
+     * @param  thread The first thread in the chain of threads to verify.
      * @return The name of dead threads, or {@code null} if none.
+     *
+     * @see Threads#listDeadThreads()
      */
-    static List<String> listDeadThreads(final DaemonThread first) {
+    static List<String> listDeadThreads(DaemonThread thread) {
         List<String> list = null;
-        for (DaemonThread thread=first; thread!=null; thread=thread.previous) {
+        while (thread != null) {
             if (!thread.isAlive()) {
                 if (list == null) {
                     list = new ArrayList<String>();
                 }
                 list.add(thread.getName());
             }
+            thread = thread.previous;
         }
         return list;
     }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java Fri Nov 30 17:38:17 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.util;
 
+import javax.management.JMException;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleActivator;
 
@@ -52,9 +53,13 @@ public final class OSGiActivator impleme
      * @param  context The execution context of the bundle being stopped.
      * @throws InterruptedException If an other thread invoked {@link #interrupt()} while
      *         we were waiting for the {@code sis-utility} threads to die.
+     * @throws JMException If an error occurred during unregistration of the supervisor MBean.
      */
     @Override
-    public void stop(final BundleContext context) throws InterruptedException {
+    public void stop(final BundleContext context) throws InterruptedException, JMException {
         Threads.shutdown(4000);
+        if (Supervisor.ENABLED) {
+            Supervisor.unregister();
+        }
     }
 }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java Fri Nov 30 17:38:17 2012
@@ -63,6 +63,9 @@ public final class ReferenceQueueConsume
         synchronized (Threads.class) {
             Threads.lastCreatedDaemon = DEFAULT = new ReferenceQueueConsumer<Object>(Threads.lastCreatedDaemon);
         }
+        if (Supervisor.ENABLED) {
+            Supervisor.register();
+        }
         // Call to Thread.start() must be outside the constructor
         // (Reference: Goetz et al.: "Java Concurrency in Practice").
         DEFAULT.start();

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java Fri Nov 30 17:38:17 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.util;
 
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.ExecutorService;
 import org.apache.sis.util.Static;
@@ -67,6 +68,14 @@ final class Threads extends Static {
         }
     };
 
+
+
+    /* -------------------------------------------------------------------------------------
+     * Every non-final static variables below this point are initialized by other classes,
+     * like DaemonThread or Executors - this class will never initialize those variables by
+     * itself. All initialization shall be performed in a synchronized (Thread.class) block.
+     * ------------------------------------------------------------------------------------- */
+
     /**
      * The tail of a chain of {@code DaemonThread}s created by the {@code sis-utility} module.
      * Other modules need to maintain their own chain, if any. See the {@link DaemonThread}
@@ -116,4 +125,15 @@ final class Threads extends Static {
         }
         DaemonThread.killAll(lastCreatedDaemon, stopWaitingAt);
     }
+
+    /**
+     * Returns the names of dead threads, or {@code null} if none. The returned list should
+     * always be null. A non-empty list would be a symptom for a severe problem, probably
+     * requiring an application reboot.
+     *
+     * @return The name of dead threads, or {@code null} if none.
+     */
+    static synchronized List<String> listDeadThreads() {
+        return DaemonThread.listDeadThreads(lastCreatedDaemon);
+    }
 }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java Fri Nov 30 17:38:17 2012
@@ -17,11 +17,16 @@
 package org.apache.sis.internal.util;
 
 import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.StringBuilders;
 
 
 /**
- * Escape codes from ANSI X3.64 standard (aka ECMA-48 and ISO/IEC 6429).
+ * A limited set of color and font attributes assignable to characters at formatting time.
+ * Those attributes are used by SIS formatters for providing some syntax coloring,
+ * for example in the <code>org.apache.sis.io.wkt</code> package.
+ *
+ * <p>This enumeration is restricted to a subset of the <cite>ANSI escape codes</cite> (a.k.a.
+ * ECMA-48, ISO/IEC 6429 and X3.64 standards) because SIS uses them mostly for syntax coloring in
+ * console outputs. However those attributes can also occasionally be used for HTML rendering.</p>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3 (derived from geotk-2.4)
@@ -131,9 +136,9 @@ public enum X364 {
     }
 
     /**
-     * Returns the X3.64 escape sequence.
+     * Returns the ANSI escape sequence.
      *
-     * @return The X3.64 escape sequence.
+     * @return The ANSI escape sequence.
      */
     public String sequence() {
         if (sequence == null) {
@@ -147,86 +152,22 @@ public enum X364 {
     }
 
     /**
-     * Replaces escape codes in the given string by HTML {@code <font>} instructions.
-     * If no HTML instruction is associated to the given escape code, then the escape
-     * sequence is removed.
-     *
-     * @param  text The text with X3.64 sequences.
-     * @return The text with HTML {@code <font>} instructions.
-     */
-    public static String toHTML(final String text) {
-        final StringBuilder buffer = new StringBuilder(text);
-        StringBuilders.replace(buffer, "&", "&amp;");
-        StringBuilders.replace(buffer, "<", "&lt;");
-        StringBuilders.replace(buffer, ">", "&gt;");
-        boolean fontApplied = false;
-        StringBuilder tmp = null;
-        for (int i=buffer.indexOf(START); i>=0; i=buffer.indexOf(START, i)) {
-            int lower  = i + START.length();
-            int upper  = lower;
-            int length = buffer.length();
-            while (upper < length) {
-                if (buffer.charAt(upper++) == END) {
-                    break;
-                }
-            }
-            final int code;
-            try {
-                code = Integer.parseInt(buffer.substring(lower, upper-1));
-            } catch (NumberFormatException e) {
-                buffer.delete(i, upper);
-                continue;
-            }
-            final String color;
-            switch (code) {
-                case 31: color="red";     break;
-                case 32: color="green";   break;
-                case 33: color="olive";   break; // "yellow" is too bright.
-                case 34: color="blue";    break;
-                case 35: color="magenta"; break;
-                case 36: color="teal";    break; // "cyan" is not in HTML 4, while "teal" is.
-                case 37: color="gray";    break;
-                case 39: // Fall through
-                case 0:  color=null; break;
-                default: {
-                    buffer.delete(i, upper);
-                    continue;
-                }
-            }
-            if (tmp == null) {
-                tmp = new StringBuilder(24);
-            }
-            if (fontApplied) {
-                tmp.append("</font>");
-                fontApplied = false;
-            }
-            if (color != null) {
-                tmp.append("<font color=\"").append(color).append("\">");
-                fontApplied = true;
-            }
-            buffer.replace(i, upper, tmp.toString());
-            tmp.setLength(0);
-        }
-        final String result = buffer.toString();
-        return result.equals(text) ? text : result;
-    }
-
-    /**
      * Removes all escape codes from the given string.
      *
-     * @param  text The string which may contains escape codes.
+     * @param  text      The string which may contains escape codes.
+     * @param  fromIndex The index from which to start the process.
+     * @param  toIndex   The index after the last character to process.
      * @return Text without the escape codes, or the given {@code text} reference if
      *         it didn't contained any escape codes.
      */
-    public static String plain(final String text) {
-        int i = text.indexOf(START);
+    public static CharSequence plain(final CharSequence text, int fromIndex, final int toIndex) {
+        int i = CharSequences.indexOf(text, START, fromIndex, toIndex);
         if (i >= 0) {
             StringBuilder buffer = null;
-            int last = 0;
 search:     do {
                 final int start = i;
                 i += START.length();
-                final int end = text.indexOf(END, i);
+                final int end = CharSequences.indexOf(text, END, i, toIndex);
                 if (end < 0) {
                     break;
                 }
@@ -237,13 +178,13 @@ search:     do {
                     }
                 }
                 if (buffer == null) {
-                    buffer = new StringBuilder(text.length() - last);
+                    buffer = new StringBuilder(toIndex - fromIndex);
                 }
-                buffer.append(text, last, start);
-                last = ++i; // The ++ is for skipping the END character.
-            } while ((i = text.indexOf(START, i)) >= 0);
+                buffer.append(text, fromIndex, start);
+                fromIndex = ++i; // The ++ is for skipping the END character.
+            } while ((i = CharSequences.indexOf(text, START, i, toIndex)) >= 0);
             if (buffer != null) {
-                return buffer.append(text, last, text.length()).toString();
+                return buffer.append(text, fromIndex, toIndex);
             }
         }
         return text;
@@ -255,20 +196,22 @@ search:     do {
      * CharSequences.codePointCount}({@linkplain #plain plain}(text))</code> without the
      * cost of creating a temporary string.
      *
-     * @param  text The string which may contains escape codes.
+     * @param  text      The string which may contains escape codes.
+     * @param  fromIndex The index from which to start the computation.
+     * @param  toIndex   The index after the last character to take in account.
      * @return The length of the given string without escape codes.
      */
-    public static int lengthOfPlain(final String text) {
-        int i = text.indexOf(START);
+    public static int lengthOfPlain(final CharSequence text, final int fromIndex, final int toIndex) {
+        int i = CharSequences.indexOf(text, START, fromIndex, toIndex);
         if (i < 0) {
-            return text.codePointCount(0, text.length());
+            return CharSequences.codePointCount(text, fromIndex, toIndex);
         }
-        int last   = 0;
+        int last   = fromIndex;
         int length = 0;
 search: do {
             final int start = i;
             i += START.length();
-            final int end = text.indexOf(END, i);
+            final int end = CharSequences.indexOf(text, END, i, toIndex);
             if (end < 0) {
                 break;
             }
@@ -278,16 +221,16 @@ search: do {
                     continue search; // Not an X.364 sequence.
                 }
             }
-            length += text.codePointCount(last, start);
+            length += CharSequences.codePointCount(text, last, start);
             last = ++i; // The ++ is for skipping the END character.
-        } while ((i = text.indexOf(START, i)) >= 0);
-        length += text.codePointCount(last, text.length());
-        assert CharSequences.codePointCount(plain(text)) == length : text;
+        } while ((i = CharSequences.indexOf(text, START, i, toIndex)) >= 0);
+        length += CharSequences.codePointCount(text, last, toIndex);
+        assert CharSequences.codePointCount(plain(text, fromIndex, toIndex)) == length : text.subSequence(fromIndex, toIndex);
         return length;
     }
 
     /**
-     * Returns {@code true} if we think that the operating system supports X3.64 sequences.
+     * Returns {@code true} if we think that the operating system supports ANSI sequences.
      * This method performs a very naive and approximative check. Result is just a hint and
      * may be wrong.
      *
@@ -296,10 +239,10 @@ search: do {
      * error stream} instead than the {@linkplain System#out standard output stream}, in which
      * case the console information is not applicable.</p>
      *
-     * @return {@code true} if we think that the operating system supports X3.64.
+     * @return {@code true} if we think that the operating system supports ANSI codes.
      *         This method may conservatively returns {@code false} in case of doubt.
      */
-    public static boolean isSupported() {
+    public static boolean isAnsiSupported() {
         String terminal;
         try {
             terminal = System.getenv("COLORTERM");

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/io/CompoundFormat.java Fri Nov 30 17:38:17 2012
@@ -227,6 +227,12 @@ public abstract class CompoundFormat<T> 
      * {@linkplain Character#isSpaceChar(int) spaces} and
      * {@linkplain Character#isISOControl(int) ISO control characters}.
      *
+     * {@note The usual SIS policy, as documented in the <code>CharSequences</code> class,
+     * is to test for whitespaces using the <code>Characters.isWhitespace(…)</code> method.
+     * The combination of <code>isSpaceChar(…)</code> and <code>isISOControl(…)</code> done
+     * in this <code>parseObject(…)</code> method is more permissive since it encompasses
+     * all whitespace characters, plus non-breaking spaces and non-white ISO controls.}
+     *
      * @param  text The string representation of the object to parse.
      * @return The parsed object.
      * @throws ParseException If an error occurred while parsing the object.
@@ -364,11 +370,18 @@ public abstract class CompoundFormat<T> 
      *         or {@code null} if none.
      */
     protected Format createFormat(final Class<?> valueType) {
-        if (valueType == Number.class) {
-            if (locale == null) return null;
-            return NumberFormat.getInstance(locale);
-        }
-        if (valueType == Date.class) {
+        /*
+         * The first case below is an apparent exception to the 'expected == type' rule
+         * documented in this method javadoc. But actually it is not, since the call to
+         * DefaultFormat.getInstance(…) will indirectly perform this kind of comparison.
+         */
+        if (Number.class.isAssignableFrom(valueType)) {
+            if (locale == null) {
+                return DefaultFormat.getInstance(valueType);
+            } else if (valueType == Number.class) {
+                return NumberFormat.getInstance(locale);
+            }
+        } else if (valueType == Date.class) {
             final DateFormat format;
             if (locale != null) {
                 format = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, locale);
@@ -376,10 +389,9 @@ public abstract class CompoundFormat<T> 
                 format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
             }
             format.setTimeZone(timezone != null ? timezone : TimeZone.getTimeZone("UTC"));
-        }
-        if (valueType == Angle.class) {
-            if (locale == null) return null;
-            return AngleFormat.getInstance(locale);
+            return format;
+        } else if (valueType == Angle.class) {
+            return AngleFormat.getInstance(locale != null ? locale : Locale.US);
         }
         return null;
     }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/io/TableFormatter.java Fri Nov 30 17:38:17 2012
@@ -19,10 +19,10 @@ package org.apache.sis.io;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.StringTokenizer;
 import java.io.Flushable;
 import java.io.IOException;
 import org.apache.sis.util.Decorator;
+import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.util.X364;
@@ -151,8 +151,8 @@ public class TableFormatter extends Filt
     /**
      * Alignment for current and next cells.
      *
-     * @see #getAlignment()
-     * @see #setAlignment(byte)
+     * @see #getCellAlignment()
+     * @see #setCellAlignment(byte)
      */
     private byte alignment = ALIGN_LEFT;
 
@@ -256,29 +256,15 @@ public class TableFormatter extends Filt
     public TableFormatter(final Appendable out, final String separator) {
         super(out);
         /*
-         * Use Character.isSpaceChar(…) instead of Character.isWhitespace(…) because the former
-         * does not consider control characters (tabulation, group separator, etc.) as spaces.
-         * We presume that if the user wants to put such characters in the border, he has reasons.
-         *
-         * If this policy is changed, search for other occurrences of 'isSpaceChar' in this class
-         * for ensuring consistency. Note however that the same policy is not necessarily applied
-         * everywhere.
+         * Following methods use Character.isWhitespace(…) instead of Character.isSpaceChar(…).
+         * This has the effect of removing some ISO control characters (line feeds, tabulation,
+         * etc.) from the border. If this policy is changed, search for other occurrences of
+         * 'isWhitespace' in this class for ensuring consistency. Note however that the same
+         * policy is not necessarily applied everywhere.
          */
         final int length = separator.length();
-        int lower = 0;
-        int upper = length;
-        while (lower < length) {
-            final int c = separator.codePointAt(lower);
-            if (!Character.isSpaceChar(c)) break;
-            lower += Character.charCount(c);
-        }
-        while (upper > 0) {
-            final int c = separator.codePointBefore(upper);
-            if (!Character.isSpaceChar(c)) break;
-            upper -= Character.charCount(c);
-        }
-        leftBorder      = separator.substring(lower);
-        rightBorder     = separator.substring(0, upper);
+        leftBorder      = separator.substring(   CharSequences.skipLeadingWhitespaces (separator, 0, length));
+        rightBorder     = separator.substring(0, CharSequences.skipTrailingWhitespaces(separator, 0, length));
         columnSeparator = separator;
     }
 
@@ -318,7 +304,7 @@ public class TableFormatter extends Filt
         assert (verticalBorder >= -1) && (verticalBorder <= +1) : verticalBorder;
         /*
          * Remplaces spaces by the horizontal lines, and vertical lines by an intersection.
-         * Use Character.isSpaceChar(…) instead of Character.isWhitespace(…) for consistency
+         * Use Character.isWhitespace(…) instead of Character.isSpaceChar(…) for consistency
          * with the policy used in the constructor, since we work on the same object (namely
          * the border strings).
          */
@@ -327,7 +313,7 @@ public class TableFormatter extends Filt
         for (int i=0; i<borderLength;) {
             int c = border.codePointAt(i);
             i += Character.charCount(c);
-            if (Character.isSpaceChar(c)) {
+            if (Character.isWhitespace(c)) {
                 c = horizontalChar;
             } else {
                 for (int j=0; j<boxCount; j++) {
@@ -373,26 +359,28 @@ public class TableFormatter extends Filt
     }
 
     /**
-     * Returns the alignment for current and next cells.
-     * The default alignment is {@link #ALIGN_LEFT}.
+     * Returns the alignment of the text inside the current cell.
+     * The default value is {@link #ALIGN_LEFT}.
      *
-     * @return Cell alignment: {@link #ALIGN_LEFT} (the default),
-     *         {@link #ALIGN_RIGHT} or {@link #ALIGN_CENTER}.
+     * @return Current cell alignment as one of the {@link #ALIGN_LEFT},
+     *         {@link #ALIGN_RIGHT} or {@link #ALIGN_CENTER} constants.
      */
-    public byte getAlignment() {
+    public byte getCellAlignment() {
         return alignment;
     }
 
     /**
-     * Sets the alignment for current and next cells. Invoking this method
-     * does does not affect the alignment of previous written cells.
+     * Sets the alignment of the text inside the current cell. The alignments of any cell
+     * written prior this method call are left unchanged. The new alignment will apply to
+     * the next cells too until this {@code setCellAlignment(…)} method is invoked again
+     * with a different value.
      *
-     * <p>The default alignment is {@link #ALIGN_LEFT}.</p>
+     * <p>If this method is never invoked, then the default alignment is {@link #ALIGN_LEFT}.</p>
      *
-     * @param alignment Cell alignment. Must be one of {@link #ALIGN_LEFT}
-     *        {@link #ALIGN_RIGHT} or {@link #ALIGN_CENTER}.
+     * @param alignment The new cell alignment as one of the {@link #ALIGN_LEFT},
+     *        {@link #ALIGN_RIGHT} or {@link #ALIGN_CENTER} constants.
      */
-    public void setAlignment(final byte alignment) {
+    public void setCellAlignment(final byte alignment) {
         if (alignment < ALIGN_LEFT || alignment > ALIGN_RIGHT) {
             throw new IllegalArgumentException(Errors.format(
                     Errors.Keys.IllegalArgument_1, "alignment"));
@@ -401,35 +389,6 @@ public class TableFormatter extends Filt
     }
 
     /**
-     * Sets the alignment for all cells in the specified column.
-     * The alignments of cells already written prior this method
-     * call are also modified.
-     *
-     * <p>The default alignment is {@link #ALIGN_LEFT}.</p>
-     *
-     * @param column The 0-based column number.
-     * @param alignment Cell alignment. Must be one of {@link #ALIGN_LEFT}
-     *        {@link #ALIGN_RIGHT} or {@link #ALIGN_CENTER}.
-     */
-    public void setColumnAlignment(final int column, final byte alignment) {
-        if (alignment < ALIGN_LEFT || alignment > ALIGN_RIGHT) {
-            throw new IllegalArgumentException(Errors.format(
-                    Errors.Keys.IllegalArgument_1, "alignment"));
-        }
-        int columnIndex = 0;
-        for (final Cell cell : cells) {
-            if (cell == null || cell.text == null) {
-                columnIndex = 0; // New line.
-            } else {
-                if (columnIndex == column) {
-                    cell.alignment = alignment;
-                }
-                columnIndex++;
-            }
-        }
-    }
-
-    /**
      * Returns the number of rows in this table. This count is reset to 0 by {@link #flush()}.
      *
      * @return The number of rows in this table.
@@ -597,16 +556,23 @@ public class TableFormatter extends Filt
         if (currentColumn >= maximalColumnWidths.length) {
             maximalColumnWidths = Arrays.copyOf(maximalColumnWidths, currentColumn+1);
         }
-        int length = 0;
-        final StringTokenizer tk = new StringTokenizer(cellText, "\r\n");
-        while (tk.hasMoreTokens()) {
-            final int lg = X364.lengthOfPlain(tk.nextToken());
-            if (lg > length) {
-                length = lg;
+        int width     = 0;
+        int lineStart = 0;
+        final int length = cellText.length();
+        while (lineStart < length) {
+            final int nextLine = CharSequences.indexOfLineStart(cellText, 1, lineStart);
+            for (int i=nextLine; --i >= lineStart;) {
+                if (!Character.isISOControl(cellText.charAt(i))) {
+                    final int lg = X364.lengthOfPlain(cellText, lineStart, i+1);
+                    if (lg > width) {
+                        width = lg;
+                    }
+                }
             }
+            lineStart = nextLine;
         }
-        if (length > maximalColumnWidths[currentColumn]) {
-            maximalColumnWidths[currentColumn] = length;
+        if (width > maximalColumnWidths[currentColumn]) {
+            maximalColumnWidths[currentColumn] = width;
         }
         currentColumn++;
         buffer.setLength(0);
@@ -782,7 +748,7 @@ public class TableFormatter extends Filt
                         endOfFirstLine = next;
                     }
                     currentLine[j] = remaining;
-                    textLength = X364.lengthOfPlain(cellText);
+                    textLength = X364.lengthOfPlain(cellText, 0, cellText.length());
                     /*
                      * If the cell to write is actually a border, do a special processing
                      * in order to use the characters defined in the BOX static constant.
@@ -796,7 +762,7 @@ public class TableFormatter extends Filt
                         if (isFirstColumn) {
                             writeBorder(-1, verticalBorder, cell.fill);
                         }
-                        repeat(out, cell.fill, Character.isSpaceChar(cell.fill) ? cellPadding : cellWidth);
+                        repeat(out, cell.fill, Character.isWhitespace(cell.fill) ? cellPadding : cellWidth);
                         writeBorder(isLastColumn ? +1 : 0, verticalBorder, cell.fill);
                         continue;
                     }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/io/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/io/package-info.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/io/package-info.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/io/package-info.java Fri Nov 30 17:38:17 2012
@@ -24,6 +24,11 @@
  * replaces all occurrence of {@code '\t'} by the amount of spaces needed for producing a tabular
  * output.
  *
+ * {@note One of the formatter classes defined in this package is a <code>java.text.Format</code>
+ * subclass. While traditionally though as part of <code>text</code> packages, that {@code Format}
+ * is defined in this I/O package because it can format to an <code>Appendable</code> and for
+ * consistency with the <code>org.apache.sis.io.wkt</code> package.}
+ *
  * {@section Unicode characters}
  * Some formatters in this package make extensive use of Unicode characters. This may produce
  * unexpected results in a Windows console, unless the underlying output stream uses the correct

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/AngleFormat.java Fri Nov 30 17:38:17 2012
@@ -1010,8 +1010,7 @@ scan:   for (int i=0; i<length;) {
 
     /**
      * Formats an angle, latitude or longitude value as an attributed character iterator.
-     * Callers can iterator over the returned iterator and queries the attribute values as
-     * in the following example:
+     * Callers can iterate and queries the attribute values as in the following example:
      *
      * {@preformat java
      *     AttributedCharacterIterator it = angleFormat.formatToCharacterIterator(myAngle);
@@ -1114,7 +1113,7 @@ scan:   for (int i=0; i<length;) {
                     c = source.codePointAt(index);
                     index += Character.charCount(c);
                 }
-                while (Character.isSpaceChar(c));
+                while (Character.isSpaceChar(c)); // Method shall be consistent with skipSpaces(…)
             }
             if (++field > SECONDS_FIELD) {
                 field = PREFIX_FIELD;
@@ -1133,7 +1132,7 @@ scan:   for (int i=0; i<length;) {
                 c = source.codePointAt(start);
                 start += Character.charCount(c);
             }
-            while (Character.isSpaceChar(c));
+            while (Character.isSpaceChar(c)); // Method shall be consistent with skipSpaces(…)
             switch (c) {
                 case '°' :            pos.setIndex(start); return DEGREES_FIELD;
                 case '′' : case '\'': pos.setIndex(start); return MINUTES_FIELD;
@@ -1145,13 +1144,20 @@ scan:   for (int i=0; i<length;) {
 
     /**
      * Returns the index of the first non-space character in the given string.
+     * This method performs the same work than {@code CharSequences.skipLeadingWhitespaces},
+     * except that it tests for spaces using the {@link Character#isSpaceChar(int)} method
+     * instead than {@link Character#isWhitespace(int)}. The reason is that we really want
+     * to skip no-break spaces, since they are often used inside a single entity (e.g. the
+     * group separator in numbers formatted using the French locale).  Furthermore we do
+     * not want to skip tabulations or line feeds, since they are unlikely to be part of
+     * the angle to parse.
      *
      * @param  source The string being parsed.
      * @param  index  Index of the first {@code source} character to read.
+     * @param  length The length of {@code source}.
      * @return Index of the first non-space character, or the end of string if none.
      */
-    private static int skipSpaces(final String source, int index) {
-        final int length = source.length();
+    private static int skipSpaces(final String source, int index, final int length) {
         while (index < length) {
             final int c = source.codePointAt(index);
             if (!Character.isSpaceChar(c)) break;
@@ -1217,7 +1223,7 @@ scan:   for (int i=0; i<length;) {
                 pos.setIndex(indexStart);
                 return null;
             }
-            index = skipSpaces(source, pos.getIndex());
+            index = skipSpaces(source, pos.getIndex(), length);
             pos.setIndex(index);
             /*
              * Parse the degrees field. If there is no separator between degrees, minutes
@@ -1278,7 +1284,7 @@ BigBoss:    switch (skipSuffix(source, p
                  */
                 case DEGREES_FIELD: {
                     final int indexStartField = pos.getIndex();
-                    index = skipSpaces(source, indexStartField);
+                    index = skipSpaces(source, indexStartField, length);
                     if (!spaceAsSeparator && index != indexStartField) {
                         break BigBoss;
                     }
@@ -1364,7 +1370,7 @@ BigBoss:    switch (skipSuffix(source, p
                         degrees = NaN;
                     }
                     final int indexStartField = pos.getIndex();
-                    index = skipSpaces(source, indexStartField);
+                    index = skipSpaces(source, indexStartField, length);
                     if (!spaceAsSeparator && index != indexStartField) {
                         break BigBoss;
                     }
@@ -1513,7 +1519,7 @@ BigBoss:    switch (skipSuffix(source, p
                 case EAST : pos.setIndex(index); return new Longitude( degrees);
                 case WEST : pos.setIndex(index); return new Longitude(-degrees);
             }
-            if (!Character.isSpaceChar(c)) {
+            if (!Character.isSpaceChar(c)) { // Method shall be consistent with skipSpaces(…)
                 break;
             }
         }
@@ -1536,7 +1542,8 @@ BigBoss:    switch (skipSuffix(source, p
         final ParsePosition pos = new ParsePosition(0);
         final Angle angle = parse(source, pos, true);
         final int offset = pos.getIndex();
-        if (skipSpaces(source, offset) != source.length()) {
+        final int length = source.length();
+        if (skipSpaces(source, offset, length) < length) {
             throw new LocalizedParseException(locale, Angle.class, source, pos);
         }
         return angle;

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java Fri Nov 30 17:38:17 2012
@@ -238,12 +238,12 @@ public final class ArgumentChecks extend
 
     /**
      * Ensures that the given floating point value is not
-     * {@linkplain Float#NaN NaN} and is greater than or equals to zero. Note that
+     * {@linkplain Float#isNaN(float) NaN} and is greater than or equals to zero. Note that
      * {@linkplain Float#POSITIVE_INFINITY positive infinity} is considered a valid value.
      *
      * @param  name   The name of the argument to be checked, used only if an exception is thrown.
      * @param  value  The user argument to check.
-     * @throws IllegalArgumentException if the given value is {@linkplain Float#NaN NaN} or negative.
+     * @throws IllegalArgumentException if the given value is NaN or negative.
      *
      * @see #ensureStrictlyPositive(String, float)
      */
@@ -259,12 +259,12 @@ public final class ArgumentChecks extend
 
     /**
      * Ensures that the given floating point value is not
-     * {@linkplain Double#NaN NaN} and is greater than or equals to zero. Note that
+     * {@linkplain Double#isNaN(double) NaN} and is greater than or equals to zero. Note that
      * {@linkplain Double#POSITIVE_INFINITY positive infinity} is considered a valid value.
      *
      * @param  name   The name of the argument to be checked, used only if an exception is thrown.
      * @param  value  The user argument to check.
-     * @throws IllegalArgumentException if the given value is {@linkplain Double#NaN NaN} or negative.
+     * @throws IllegalArgumentException if the given value is NaN or negative.
      *
      * @see #ensureStrictlyPositive(String, double)
      */
@@ -316,13 +316,12 @@ public final class ArgumentChecks extend
 
     /**
      * Ensures that the given floating point value is not
-     * {@linkplain Float#NaN NaN} and is greater than zero. Note that
+     * {@linkplain Float#isNaN(float) NaN} and is greater than zero. Note that
      * {@linkplain Float#POSITIVE_INFINITY positive infinity} is considered a valid value.
      *
      * @param  name   The name of the argument to be checked, used only if an exception is thrown.
      * @param  value  The user argument to check.
-     * @throws IllegalArgumentException if the given value is {@linkplain Float#NaN NaN},
-     *         zero or negative.
+     * @throws IllegalArgumentException if the given value is NaN, zero or negative.
      *
      * @see #ensurePositive(String, float)
      */
@@ -338,13 +337,12 @@ public final class ArgumentChecks extend
 
     /**
      * Ensures that the given floating point value is not
-     * {@linkplain Double#NaN NaN} and is greater than zero. Note that
+     * {@linkplain Double#isNaN(double) NaN} and is greater than zero. Note that
      * {@linkplain Double#POSITIVE_INFINITY positive infinity} is considered a valid value.
      *
      * @param  name   The name of the argument to be checked, used only if an exception is thrown.
      * @param  value  The user argument to check.
-     * @throws IllegalArgumentException if the given value is {@linkplain Double#NaN NaN},
-     *         zero or negative.
+     * @throws IllegalArgumentException if the given value is NaN, zero or negative.
      *
      * @see #ensurePositive(String, double)
      */
@@ -359,6 +357,40 @@ public final class ArgumentChecks extend
     }
 
     /**
+     * Ensures that the given floating point value is not
+     * {@linkplain Float#isNaN(float) NaN} neither {@linkplain Float#isInfinite(float)}.
+     * The value can be negative, zero or positive.
+     *
+     * @param  name   The name of the argument to be checked, used only if an exception is thrown.
+     * @param  value  The user argument to check.
+     * @throws IllegalArgumentException if the given value is NaN or infinite.
+     */
+    public static void ensureFinite(final String name, final float value) {
+        final boolean isNaN;
+        if ((isNaN = Float.isNaN(value)) == true || Float.isInfinite(value)) {
+            throw new IllegalArgumentException(Errors.format(isNaN ?
+                    Errors.Keys.NotANumber_1 : Errors.Keys.InfiniteArgumentValue_1, name));
+        }
+    }
+
+    /**
+     * Ensures that the given floating point value is not
+     * {@linkplain Double#isNaN(double) NaN} neither {@linkplain Double#isInfinite(double)}.
+     * The value can be negative, zero or positive.
+     *
+     * @param  name   The name of the argument to be checked, used only if an exception is thrown.
+     * @param  value  The user argument to check.
+     * @throws IllegalArgumentException if the given value is NaN or infinite.
+     */
+    public static void ensureFinite(final String name, final double value) {
+        final boolean isNaN;
+        if ((isNaN = Double.isNaN(value)) == true || Double.isInfinite(value)) {
+            throw new IllegalArgumentException(Errors.format(isNaN ?
+                    Errors.Keys.NotANumber_1 : Errors.Keys.InfiniteArgumentValue_1, name));
+        }
+    }
+
+    /**
      * Ensures that the given integer value is between the given bounds, inclusive.
      *
      * @param  name  The name of the argument to be checked. Used only in case an exception is thrown.
@@ -403,8 +435,7 @@ public final class ArgumentChecks extend
      * @param  min   The minimal value, inclusive.
      * @param  max   The maximal value, inclusive.
      * @param  value The value to be tested.
-     * @throws IllegalArgumentException if the given value is {@linkplain Float#NaN NaN}
-     *         or not in the given range.
+     * @throws IllegalArgumentException if the given value is NaN or not in the given range.
      */
     public static void ensureBetween(final String name, final float min, final float max, final float value)
             throws IllegalArgumentException
@@ -423,8 +454,7 @@ public final class ArgumentChecks extend
      * @param  min   The minimal value, inclusive.
      * @param  max   The maximal value, inclusive.
      * @param  value The value to be tested.
-     * @throws IllegalArgumentException if the given value is {@linkplain Float#NaN NaN}
-     *         or not in the given range.
+     * @throws IllegalArgumentException if the given value is NaN or not in the given range.
      */
     public static void ensureBetween(final String name, final double min, final double max, final double value)
             throws IllegalArgumentException

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java Fri Nov 30 17:38:17 2012
@@ -39,6 +39,39 @@ import static org.apache.sis.internal.ut
  * when appropriate. Consequently those methods should behave correctly with characters outside
  * the <cite>Basic Multilingual Plane</cite> (BMP).
  *
+ * {@section Policy on space characters}
+ * Java defines two methods for testing if a character is a white space:
+ * {@link Character#isWhitespace(int)} and {@link Character#isSpaceChar(int)}.
+ * Those two methods differ in the way they handle {@linkplain Characters#NO_BREAK_SPACE
+ * no-break spaces}, tabulations and line feeds. The general policy in the SIS library is:
+ *
+ * <ul>
+ *   <li>Use {@code isWhitespace(…)} when separating entities (words, numbers, tokens, <i>etc.</i>)
+ *       in a list. Using that method, characters separated by a no-break space are considered as
+ *       part of the same entity.</li>
+ *   <li>Use {@code isSpaceChar(…)} when parsing a single entity, for example a single word.
+ *       Using this method, no-break spaces are considered as part of the entity while line
+ *       feeds or tabulations are entity boundaries.</li>
+ * </ul>
+ *
+ * <blockquote><font size="-1"><b>Example:</b> Numbers formatted in the French locale use no-break
+ * spaces as group separators. When parsing a list of numbers, ordinary spaces around the numbers
+ * may need to be ignored, but no-break spaces shall be considered as part of the numbers.
+ * Consequently {@code isWhitespace(…)} is appropriate for skipping spaces <em>between</em> the numbers.
+ * But if there is spaces to skip <em>inside</em> a single number, then {@code isSpaceChar(…)} is a
+ * good choice for accepting no-break spaces and for stopping the parse operation at tabulations or
+ * line feed character. A tabulation or line feed between two characters is very likely to separate
+ * two distinct values.</font></blockquote>
+ *
+ * In practice, the {@link java.text.Format} implementations in the SIS library typically use
+ * {@code isSpaceChar(…)} while most of the rest of the SIS library, including this
+ * {@code CharSequences} class, consistently uses {@code isWhitespace(…)}.
+ *
+ * <p>Note that the {@link String#trim()} method doesn't follow any of those policies and should
+ * generally be avoided. That {@code trim()} method removes every ISO control characters without
+ * distinction about whether the characters are space or not, and ignore all Unicode spaces.
+ * The {@link #trimWhitespaces(String)} method defined in this class can be used as an alternative.</p>
+ *
  * {@section Handling of null values}
  * Most methods in this class accept a {@code null} {@code CharSequence} argument. In such cases
  * the method return value is either a {@code null} {@code CharSequence}, an empty array, or a
@@ -164,7 +197,7 @@ public final class CharSequences extends
      * @param  text The character sequence from which to get the count, or {@code null}.
      * @return The number of Unicode code points, or 0 if the argument is {@code null}.
      *
-     * @see Character#codePointCount(CharSequence, int, int)
+     * @see #codePointCount(CharSequence, int, int)
      */
     public static int codePointCount(final CharSequence text) {
         if (text == null)                  return 0;
@@ -181,6 +214,40 @@ public final class CharSequences extends
     }
 
     /**
+     * Returns the number of Unicode code points in the given characters sub-sequence,
+     * or 0 if {@code null}. Unpaired surrogates within the text count as one code
+     * point each.
+     *
+     * <p>This method performs the same work than the standard
+     * {@link Character#codePointCount(CharSequence, int, int)} method, except that it tries
+     * to delegate to the optimized methods from the {@link String}, {@link StringBuilder},
+     * {@link StringBuffer} or {@link CharBuffer} classes if possible.</p>
+     *
+     * @param  text      The character sequence from which to get the count, or {@code null}.
+     * @param  fromIndex The index from which to start the computation.
+     * @param  toIndex   The index after the last character to take in account.
+     * @return The number of Unicode code points, or 0 if the argument is {@code null}.
+     *
+     * @see Character#codePointCount(CharSequence, int, int)
+     * @see String#codePointCount(int, int)
+     * @see StringBuilder#codePointCount(int, int)
+     */
+    public static int codePointCount(final CharSequence text, final int fromIndex, final int toIndex) {
+        if (text == null)                  return 0;
+        if (text instanceof String)        return ((String)        text).codePointCount(fromIndex, toIndex);
+        if (text instanceof StringBuilder) return ((StringBuilder) text).codePointCount(fromIndex, toIndex);
+        if (text instanceof StringBuffer)  return ((StringBuffer)  text).codePointCount(fromIndex, toIndex);
+        if (text instanceof CharBuffer) {
+            final CharBuffer buffer = (CharBuffer) text;
+            if (buffer.hasArray() && !buffer.isReadOnly()) {
+                final int position = buffer.position();
+                return Character.codePointCount(buffer.array(), position + fromIndex, position + toIndex);
+            }
+        }
+        return Character.codePointCount(text, fromIndex, toIndex);
+    }
+
+    /**
      * Returns the number of occurrences of the {@code toSearch} string in the given {@code text}.
      * The search is case-sensitive.
      *
@@ -419,6 +486,81 @@ search:     for (; fromIndex <= toIndex;
     }
 
     /**
+     * Returns the index of the first character after all leading whitespace characters
+     * in the given range. If the given range contains only space characters, then this method
+     * returns the index of the first character after the given range, which is always equals
+     * or greater than {@code toIndex}. Note that this character may not exist if {@code toIndex}
+     * is equals to the text length.
+     *
+     * <p>Special cases:</p>
+     * <ul>
+     *   <li>If {@code fromIndex} is greater than {@code toIndex},
+     *       then this method unconditionally returns {@code fromIndex}.</li>
+     *   <li>If the given range contains only space characters and the character at {@code toIndex-1}
+     *       is the high surrogate of a valid supplementary code point, then this method returns
+     *       {@code toIndex+1} since that value is the index of the next code point.</li>
+     *   <li>If {@code fromIndex} is negative or {@code toIndex} is greater than the text length,
+     *       then the behavior of this method is undefined.</li>
+     * </ul>
+     *
+     * Space characters are identified by the {@link Character#isWhitespace(int)} method.
+     *
+     * @param  text      The string in which to perform the search (can not be null).
+     * @param  fromIndex The index from which to start the search (can not be negative).
+     * @param  toIndex   The index after the last character where to perform the search.
+     * @return The index within the text of the first occurrence of a non-space character, starting
+     *         at the specified index, or a value equals or greater than {@code toIndex} if none.
+     *
+     * @see #skipTrailingWhitespaces(CharSequence, int, int)
+     * @see #trimWhitespaces(CharSequence)
+     */
+    public static int skipLeadingWhitespaces(final CharSequence text, int fromIndex, final int toIndex) {
+        while (fromIndex < toIndex) {
+            final int c = Character.codePointAt(text, fromIndex);
+            if (!Character.isWhitespace(c)) break;
+            fromIndex += Character.charCount(c);
+        }
+        return fromIndex;
+    }
+
+    /**
+     * Returns the index of the last character before all trailing whitespace characters
+     * in the given range. If the given range contains only space characters, then this method
+     * returns the index of the first character in the given range, which is always equals or
+     * lower than {@code fromIndex}.
+     *
+     * <p>Special cases:</p>
+     * <ul>
+     *   <li>If {@code toIndex} 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
+     *       {@code fromIndex-1} since that value is the index of the code point.</li>
+     *   <li>If {@code fromIndex} is negative or {@code toIndex} is greater than the text length,
+     *       then the behavior of this method is undefined.</li>
+     * </ul>
+     *
+     * Space characters are identified by the {@link Character#isWhitespace(int)} method.
+     *
+     * @param  text      The string in which to perform the search (can not be null).
+     * @param  fromIndex The index from which to start the search (can not be negative).
+     * @param  toIndex   The index after the last character where to perform the search.
+     * @return The index within the text of the last occurrence of a non-space character, starting
+     *         at the specified index, or a value equals or lower than {@code fromIndex} if none.
+     *
+     * @see #skipLeadingWhitespaces(CharSequence, int, int)
+     * @see #trimWhitespaces(CharSequence)
+     */
+    public static int skipTrailingWhitespaces(final CharSequence text, final int fromIndex, int toIndex) {
+        while (toIndex > fromIndex) {
+            final int c = Character.codePointBefore(text, toIndex);
+            if (!Character.isWhitespace(c)) break;
+            toIndex -= Character.charCount(c);
+        }
+        return toIndex;
+    }
+
+    /**
      * Splits a text around the given character. The array returned by this method contains all
      * subsequences of the given text that is terminated by the given character or is terminated
      * by the end of the text. The subsequences in the array are in the order in which they occur
@@ -434,7 +576,7 @@ search:     for (; fromIndex <= toIndex;
      *   <li>The separator is a simple character instead than a regular expression.</li>
      *   <li>If the {@code separator} argument is {@code '\n'} or {@code '\r'}, then this method
      *       splits around any of {@code "\r"}, {@code "\n"} or {@code "\r\n"} characters sequences.
-     *   <li>The leading and trailing spaces of each subsequences are {@linkplain #trimWhitespaces trimmed}.</li>
+     *   <li>The leading and trailing spaces of each subsequences are trimmed.</li>
      * </ul>
      *
      * @param  text The text to split, or {@code null}.
@@ -456,7 +598,7 @@ search:     for (; fromIndex <= toIndex;
             }
             return strings;
         }
-        // 'excludeEmpty' must use the same criterion than trimWhitespaces(...).
+        // 'excludeEmpty' must use the same criterion than trimWhitespaces(…).
         final boolean excludeEmpty = isWhitespace(separator);
         CharSequence[] strings = new CharSequence[4];
         final int length = text.length();
@@ -593,7 +735,7 @@ search:     for (; fromIndex <= toIndex;
         final CharSequence[] tokens = split(values, separator);
         final double[] parsed = new double[tokens.length];
         for (int i=0; i<tokens.length; i++) {
-            final String token = tokens[i].toString().trim();
+            final String token = trimWhitespaces(tokens[i]).toString();
             parsed[i] = token.isEmpty() ? Double.NaN : Double.parseDouble(token);
         }
         return parsed;
@@ -616,7 +758,7 @@ search:     for (; fromIndex <= toIndex;
         final CharSequence[] tokens = split(values, separator);
         final float[] parsed = new float[tokens.length];
         for (int i=0; i<tokens.length; i++) {
-            final String token = tokens[i].toString().trim();
+            final String token = trimWhitespaces(tokens[i]).toString();
             parsed[i] = token.isEmpty() ? Float.NaN : Float.parseFloat(token);
         }
         return parsed;
@@ -639,7 +781,7 @@ search:     for (; fromIndex <= toIndex;
         final CharSequence[] tokens = split(values, separator);
         final long[] parsed = new long[tokens.length];
         for (int i=0; i<tokens.length; i++) {
-            parsed[i] = Long.parseLong(tokens[i].toString().trim(), radix);
+            parsed[i] = Long.parseLong(trimWhitespaces(tokens[i]).toString(), radix);
         }
         return parsed;
     }
@@ -661,7 +803,7 @@ search:     for (; fromIndex <= toIndex;
         final CharSequence[] tokens = split(values, separator);
         final int[] parsed = new int[tokens.length];
         for (int i=0; i<tokens.length; i++) {
-            parsed[i] = Integer.parseInt(tokens[i].toString().trim(), radix);
+            parsed[i] = Integer.parseInt(trimWhitespaces(tokens[i]).toString(), radix);
         }
         return parsed;
     }
@@ -683,7 +825,7 @@ search:     for (; fromIndex <= toIndex;
         final CharSequence[] tokens = split(values, separator);
         final short[] parsed = new short[tokens.length];
         for (int i=0; i<tokens.length; i++) {
-            parsed[i] = Short.parseShort(tokens[i].toString().trim(), radix);
+            parsed[i] = Short.parseShort(trimWhitespaces(tokens[i]).toString(), radix);
         }
         return parsed;
     }
@@ -705,7 +847,7 @@ search:     for (; fromIndex <= toIndex;
         final CharSequence[] tokens = split(values, separator);
         final byte[] parsed = new byte[tokens.length];
         for (int i=0; i<tokens.length; i++) {
-            parsed[i] = Byte.parseByte(tokens[i].toString().trim(), radix);
+            parsed[i] = Byte.parseByte(trimWhitespaces(tokens[i]).toString(), radix);
         }
         return parsed;
     }
@@ -778,20 +920,41 @@ search:     for (; fromIndex <= toIndex;
     }
 
     /**
-     * Returns a text with leading and trailing white spaces omitted. White spaces are identified
-     * by the {@link Character#isWhitespace(int)} method.
+     * Returns a string with leading and trailing whitespace characters omitted.
+     * This method is similar in purpose to {@link String#trim()}, except that the later considers
+     * every {@linkplain Character#isISOControl(int) ISO control codes} below 32 to be a whitespace.
+     * That {@code String.trim()} behavior has the side effect of removing the heading of ANSI escape
+     * sequences (a.k.a. X3.64), and to ignore Unicode spaces. This {@code trimWhitespaces(…)} method
+     * is built on the more accurate {@link Character#isWhitespace(int)} method instead.
+     *
+     * <p>This method performs the same work than {@link #trimWhitespaces(CharSequence)},
+     * but is overloaded for the {@code String} type because of its frequent use.</p>
+     *
+     * @param  text The text from which to remove leading and trailing whitespaces, or {@code null}.
+     * @return A string with leading and trailing whitespaces removed, or {@code null} is the given
+     *         text was null.
+     */
+    public static String trimWhitespaces(String text) {
+        if (text != null) {
+            final int length = text.length();
+            final int lower = skipLeadingWhitespaces(text, 0, length);
+            text = text.substring(lower, skipTrailingWhitespaces(text, lower, length));
+        }
+        return text;
+    }
+
+    /**
+     * Returns a text with leading and trailing whitespace characters omitted.
+     * Space characters are identified by the {@link Character#isWhitespace(int)} method.
      *
-     * <p>This method is similar in purpose to {@link String#trim()}, except that the later considers
-     * every ASCII control codes below 32 to be a whitespace. This have the side effect of removing
-     * ANSI escape sequences (a.k.a. X3.64) as well. Users should invoke this
-     * {@code CharSequences.trimWhitespaces} method instead if they need to preserve
-     * those ANSI escape sequences.</p>
+     * <p>This method is the generic version of {@link #trimWhitespaces(String)}.</p>
      *
-     * @param  text The text from which to remove leading and trailing white spaces, or {@code null}.
-     * @return A characters sequence with leading and trailing white spaces removed,
+     * @param  text The text from which to remove leading and trailing whitespaces, or {@code null}.
+     * @return A characters sequence with leading and trailing whitespaces removed,
      *         or {@code null} is the given text was null.
      *
-     * @see String#trim()
+     * @see #skipLeadingWhitespaces(CharSequence, int, int)
+     * @see #skipTrailingWhitespaces(CharSequence, int, int)
      */
     public static CharSequence trimWhitespaces(CharSequence text) {
         if (text != null) {
@@ -801,13 +964,16 @@ search:     for (; fromIndex <= toIndex;
     }
 
     /**
-     * Returns a sub-sequence with leading and trailing white spaces omitted.
-     * White spaces are identified by the {@link Character#isWhitespace(int)} method.
+     * Returns a sub-sequence with leading and trailing whitespace characters omitted.
+     * Space characters are identified by the {@link Character#isWhitespace(int)} method.
+     *
+     * <p>Invoking this method is functionally equivalent to the following code snippet,
+     * except that the {@link CharSequence#subSequence(int, int) subSequence} method is
+     * invoked only once instead of two times:</p>
      *
-     * <p>Invoking this method is functionally equivalent to invoking
-     * <code>{@linkplain #trimWhitespaces(CharSequence) trimWhitespaces}(text.subSequence(lower,
-     * upper))</code>, except that only one call to {@link CharSequence#subSequence(int, int)}
-     * is performed instead of two.</p>
+     * {@preformat java
+     *     text = trimWhitespaces(text.subSequence(lower, upper));
+     * }
      *
      * @param  text  The text from which to remove leading and trailing white spaces.
      * @param  lower Index of the first character to consider for inclusion in the sub-sequence.
@@ -816,18 +982,15 @@ search:     for (; fromIndex <= toIndex;
      * @throws NullPointerException If {@code text} is {@code null}.
      * @throws IndexOutOfBoundsException If {@code lower} or {@code upper} is out of bounds.
      */
-    private static CharSequence trimWhitespaces(final CharSequence text, int lower, int upper) {
-        while (upper != 0) {
-            final int c = codePointBefore(text, upper);
-            if (!isWhitespace(c)) break;
-            upper -= charCount(c);
-        }
-        while (lower < upper) {
-            final int c = codePointAt(text, lower);
-            if (!isWhitespace(c)) break;
-            lower += charCount(c);
+    public static CharSequence trimWhitespaces(CharSequence text, int lower, int upper) {
+        final int length = text.length();
+        ArgumentChecks.ensureValidIndexRange(length, lower, upper);
+        lower = skipLeadingWhitespaces (text, lower, upper);
+        upper = skipTrailingWhitespaces(text, lower, upper);
+        if (lower != 0 || upper != length) { // Safety in case subSequence doesn't make the check.
+            text = text.subSequence(lower, upper);
         }
-        return text.subSequence(lower, upper);
+        return text;
     }
 
     /**

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Exceptions.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Exceptions.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Exceptions.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Exceptions.java Fri Nov 30 17:38:17 2012
@@ -22,6 +22,8 @@ import java.util.Locale;
 import java.sql.SQLException;
 import org.apache.sis.internal.util.LocalizedException;
 
+import static org.apache.sis.util.CharSequences.trimWhitespaces;
+
 // Related to JDK7
 import org.apache.sis.internal.util.JDK7;
 
@@ -86,9 +88,9 @@ public final class Exceptions extends St
     @SuppressWarnings("unchecked")
     public static <T extends Throwable> T setMessage(final T exception, String message, final boolean append) {
         if (append) {
-            String em = exception.getLocalizedMessage();
-            if (em != null && !(em = em.trim()).isEmpty()) {
-                final StringBuilder buffer = new StringBuilder(message.trim());
+            final String em = trimWhitespaces(exception.getLocalizedMessage());
+            if (em != null && !em.isEmpty()) {
+                final StringBuilder buffer = new StringBuilder(trimWhitespaces(message));
                 final int length = buffer.length();
                 if (length != 0 && Character.isLetterOrDigit(buffer.charAt(length-1))) {
                     buffer.append(". ");
@@ -125,17 +127,18 @@ public final class Exceptions extends St
      *         and no exception provide a message.
      */
     public static String formatChainedMessages(final Locale locale, String header, Throwable cause) {
-        Set<String> done = null;
+        Set<CharSequence> done = null;
         String lineSeparator = null;
         StringBuilder buffer = null;
         while (cause != null) {
-            String message = getLocalizedMessage(cause, locale);
-            if (message != null && !(message = message.trim()).isEmpty()) {
+            final String message = trimWhitespaces(getLocalizedMessage(cause, locale));
+            if (message != null && !message.isEmpty()) {
                 if (buffer == null) {
-                    done = new HashSet<String>();
+                    done = new HashSet<CharSequence>();
                     buffer = new StringBuilder(128);
                     lineSeparator = JDK7.lineSeparator();
-                    if (header != null && !(header = header.trim()).isEmpty()) {
+                    header = trimWhitespaces(header);
+                    if (header != null && !header.isEmpty()) {
                         buffer.append(header);
                         done.add(header);
                         /*
@@ -147,7 +150,7 @@ public final class Exceptions extends St
                          */
                         int s=0;
                         while ((s=header.indexOf(':', s)) >= 0) {
-                            done.add(header.substring(++s).trim());
+                            done.add(trimWhitespaces(header, ++s, header.length()));
                         }
                     }
                 }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Locales.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Locales.java?rev=1415758&r1=1415757&r2=1415758&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Locales.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Locales.java Fri Nov 30 17:38:17 2012
@@ -30,6 +30,7 @@ import org.apache.sis.util.logging.Loggi
 import org.apache.sis.util.resources.Errors;
 
 import static org.apache.sis.util.Arrays.resize;
+import static org.apache.sis.util.CharSequences.trimWhitespaces;
 import static org.apache.sis.util.collection.Collections.hashMapCapacity;
 
 
@@ -229,18 +230,18 @@ public final class Locales extends Stati
         final String language, country, variant;
         int ci = code.indexOf('_');
         if (ci < 0) {
-            language = code.trim();
+            language = trimWhitespaces(code);
             country  = "";
             variant  = "";
         } else {
-            language = code.substring(0, ci).trim();
+            language = (String) trimWhitespaces(code, 0, ci);
             int vi = code.indexOf('_', ++ci);
             if (vi < 0) {
-                country = code.substring(ci).trim();
+                country = (String) trimWhitespaces(code, ci, code.length());
                 variant = "";
             } else {
-                country = code.substring(ci, vi).trim();
-                variant = code.substring(++vi).trim();
+                country = (String) trimWhitespaces(code, ci, vi);
+                variant = (String) trimWhitespaces(code, ++vi, code.length());
                 if (code.indexOf('_', vi) >= 0) {
                     throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalLanguageCode_1, code));
                 }



Mime
View raw message