sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1420668 [1/3] - in /sis/trunk: ./ ide-project/NetBeans/ ide-project/NetBeans/nbproject/ sis-metadata/src/main/java/org/apache/sis/internal/ sis-utility/src/main/java/org/apache/sis/internal/jaxb/ sis-utility/src/main/java/org/apache/sis/in...
Date Wed, 12 Dec 2012 13:38:24 GMT
Author: desruisseaux
Date: Wed Dec 12 13:38:18 2012
New Revision: 1420668

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

Added:
    sis/trunk/sis-metadata/src/main/java/org/apache/sis/internal/
      - copied from r1420597, sis/branches/JDK6/sis-metadata/src/main/java/org/apache/sis/internal/
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/CharSequenceAdapter.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/CharSequenceAdapter.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Boolean.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Boolean.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_CharacterString.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_CharacterString.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Decimal.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Decimal.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_GenericName.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_GenericName.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Integer.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Integer.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Real.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Real.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/InternationalStringConverter.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/InternationalStringConverter.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/LocalNameAdapter.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/LocalNameAdapter.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/ScopedNameAdapter.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/ScopedNameAdapter.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gmd/
      - copied from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gmd/
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gmx/
      - copied from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gmx/
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DefaultFactories.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/DefaultFactories.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/iso/
      - copied from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/iso/
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/IdentifierAlreadyBoundException.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/xml/IdentifierAlreadyBoundException.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/ValueConverter.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/xml/ValueConverter.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/XML.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/xml/XML.java
    sis/trunk/sis-utility/src/main/resources/org/apache/sis/util/iso/
      - copied from r1420601, sis/trunk/sis-utility/src/main/resources/org/apache/sis/util/type/
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java
      - copied unchanged from r1420597, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/iso/
      - copied from r1420597, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/iso/
Removed:
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/ObjectConverters.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/ObjectResolver.java
    sis/trunk/sis-utility/src/main/resources/org/apache/sis/util/type/
    sis/trunk/sis-utility/src/test/java/org/apache/sis/util/type/
Modified:
    sis/trunk/   (props changed)
    sis/trunk/ide-project/NetBeans/build.xml
    sis/trunk/ide-project/NetBeans/nbproject/genfiles.properties
    sis/trunk/ide-project/NetBeans/nbproject/project.properties
    sis/trunk/ide-project/NetBeans/nbproject/project.xml
    sis/trunk/pom.xml
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapWithSpecialCases.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/SpecializedIdentifier.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/UUIDs.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/package-info.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/simple/SimpleCitation.java
    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/LocalizedParseException.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/LineFormatter.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/Angle.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/Characters.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Classes.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/LenientComparable.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/Static.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Version.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/UnmodifiableArrayList.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameFactory.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/iso/Types.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.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/ResourceInternationalString.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/package-info.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/IdentifiedObject.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/IdentifierMap.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/MarshalContext.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/NilObject.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/NilObjectHandler.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/XLink.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/package-info.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/jaxb/IdentifierMapAdapterTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/jaxb/IdentifierMapWithSpecialCasesTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/measure/AngleFormatTest.java
    sis/trunk/sis-utility/src/test/java/org/apache/sis/measure/UnitsTest.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/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/CharactersTest.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/xml/XLinkTest.java
    sis/trunk/src/main/docbook/fr/XML.xml
    sis/trunk/src/main/docbook/fr/geoapi.xml
    sis/trunk/src/main/docbook/fr/utility.xml
    sis/trunk/src/main/javadoc/stylesheet.css

Propchange: sis/trunk/
------------------------------------------------------------------------------
  Merged /sis/branches/JDK7:r1416133-1420581
  Merged /sis/branches/JDK6:r1416136-1420597

Modified: sis/trunk/ide-project/NetBeans/build.xml
URL: http://svn.apache.org/viewvc/sis/trunk/ide-project/NetBeans/build.xml?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/ide-project/NetBeans/build.xml (original)
+++ sis/trunk/ide-project/NetBeans/build.xml Wed Dec 12 13:38:18 2012
@@ -12,8 +12,8 @@
     can be built by the NetBeans IDE.
   -->
   <target name="-pre-jar">
-    <copy todir="${build.classes.dir}/org/apache/sis/util/type">
-      <fileset dir="${project.root}/sis-utility/src/main/resources/org/apache/sis/util/type">
+    <copy todir="${build.classes.dir}/org/apache/sis/util/iso">
+      <fileset dir="${project.root}/sis-utility/src/main/resources/org/apache/sis/util/iso">
         <include name="class-index.properties"/>
       </fileset>
     </copy>

Modified: sis/trunk/ide-project/NetBeans/nbproject/genfiles.properties
URL: http://svn.apache.org/viewvc/sis/trunk/ide-project/NetBeans/nbproject/genfiles.properties?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/ide-project/NetBeans/nbproject/genfiles.properties (original)
+++ sis/trunk/ide-project/NetBeans/nbproject/genfiles.properties Wed Dec 12 13:38:18 2012
@@ -3,6 +3,6 @@
 build.xml.data.CRC32=58e6b21c
 build.xml.script.CRC32=462eaba0
 build.xml.stylesheet.CRC32=28e38971@1.53.1.46
-nbproject/build-impl.xml.data.CRC32=6543dee2
+nbproject/build-impl.xml.data.CRC32=8695cc09
 nbproject/build-impl.xml.script.CRC32=a54bea32
 nbproject/build-impl.xml.stylesheet.CRC32=6ddba6b6@1.53.1.46

Modified: sis/trunk/ide-project/NetBeans/nbproject/project.properties
URL: http://svn.apache.org/viewvc/sis/trunk/ide-project/NetBeans/nbproject/project.properties?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/ide-project/NetBeans/nbproject/project.properties (original)
+++ sis/trunk/ide-project/NetBeans/nbproject/project.properties Wed Dec 12 13:38:18 2012
@@ -48,7 +48,7 @@ jdom.version         = 1.0
 servlet.version      = 2.4
 jcip.version         = 1.0
 osgi.version         = 5.0.0
-junit.version        = 4.8.2
+junit.version        = 4.10
 
 #
 # Classpaths for compilation, execution and tests.

Modified: sis/trunk/ide-project/NetBeans/nbproject/project.xml
URL: http://svn.apache.org/viewvc/sis/trunk/ide-project/NetBeans/nbproject/project.xml?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/ide-project/NetBeans/nbproject/project.xml (original)
+++ sis/trunk/ide-project/NetBeans/nbproject/project.xml Wed Dec 12 13:38:18 2012
@@ -35,6 +35,7 @@
             <word>namespaces</word>
             <word>timezone</word>
             <word>Unicode</word>
+            <word>unmarshal</word>
             <word>unmarshalling</word>
             <word>whitespaces</word>
         </spellchecker-wordlist>

Modified: sis/trunk/pom.xml
URL: http://svn.apache.org/viewvc/sis/trunk/pom.xml?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/pom.xml (original)
+++ sis/trunk/pom.xml Wed Dec 12 13:38:18 2012
@@ -406,6 +406,24 @@ Apache SIS is a toolkit for describing l
           <outputEncoding>${website.encoding}</outputEncoding>
         </configuration>
       </plugin>
+
+      <!-- Dependencies requires for the SIS FindBugs configuration file.
+           This dependency should be declared in the <reporting> section,
+           but Maven 3.0.4 does not support dependency declaration there.
+           Note that the version number is duplicated in the <reporting>
+           section, because <reporting> ignores <pluginManagement>. -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>2.5.2</version>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.sis</groupId>
+            <artifactId>sis-build-helper</artifactId>
+            <version>${project.version}</version>
+          </dependency>
+        </dependencies>
+      </plugin>
     </plugins>
 
     <!-- Following plugins are used only by some specific modules. -->
@@ -527,14 +545,17 @@ Apache SIS is a toolkit for describing l
         <version>1.0-alpha-3</version>
       </plugin>
 
-      <!-- FindBugs Report -->
+      <!-- FindBugs Report. Checkstyle configuration instructions apply also to FindBugs:
+           http://maven.apache.org/plugins/maven-checkstyle-plugin/examples/multi-module-config.html
+      -->
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>findbugs-maven-plugin</artifactId>
-        <version>2.5.2</version>
+        <version>2.5.2</version> <!-- See also the same plugin in the <build> section. -->
         <configuration>
           <threshold>Normal</threshold>
           <effort>Default</effort>
+          <excludeFilterFile>org/apache/sis/findbugs-exclude.xml</excludeFilterFile>
        </configuration>
       </plugin>
     </plugins>

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapAdapter.java Wed Dec 12 13:38:18 2012
@@ -28,14 +28,15 @@ import java.io.Serializable;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.xml.IdentifierSpace;
 import org.apache.sis.xml.IdentifierMap;
+import org.apache.sis.xml.IdentifierSpace;
+import org.apache.sis.xml.IdentifierAlreadyBoundException;
+
+import static org.apache.sis.util.collection.Collections.hashMapCapacity;
 
 // Related to JDK7
 import org.apache.sis.internal.util.Objects;
 
-import static org.apache.sis.util.collection.Collections.hashMapCapacity;
-
 
 /**
  * A map of identifiers which can be used as a helper class for
@@ -106,16 +107,6 @@ public class IdentifierMapAdapter extend
     private transient Set<Entry<Citation,String>> entries;
 
     /**
-     * Creates an identifier map for the given collection of identifiers.
-     *
-     * @param  identifiers The identifiers to wrap in a map view.
-     * @return The map of identifiers as a wrapper over the given collection.
-     */
-    public static IdentifierMap create(final Collection<Identifier> identifiers) {
-        return new IdentifierMapWithSpecialCases(identifiers);
-    }
-
-    /**
      * Creates a new map which will be a view over the given identifiers.
      *
      * @param identifiers The identifiers to wrap in a map view.
@@ -200,6 +191,25 @@ public class IdentifierMapAdapter extend
     }
 
     /**
+     * Returns the code of the first identifier associated with the given authority only if
+     * if is <strong>not</strong> a specialized identifier. Otherwise returns {@code null}.
+     *
+     * <p>This is a helper method for {@link IdentifierMapWithSpecialCases#put(Citation, String)},
+     * in order to be able to return the old value if that value was a {@link String} rather than
+     * the specialized type. We do not return the string for the specialized case in order to avoid
+     * the cost of invoking {@code toString()} on the specialized object (some may be costly). Such
+     * call would be useless because {@code IdentifierMapWithSpecialCase} discard the value of this
+     * method when it found a specialized type.</p>
+     */
+    final String getUnspecialized(final Citation authority) {
+        final Identifier identifier = getIdentifier(authority);
+        if (identifier != null && !(identifier instanceof SpecializedIdentifier<?>)) {
+            return identifier.getCode();
+        }
+        return null;
+    }
+
+    /**
      * Returns the code of the first identifier associated with the given
      * {@linkplain Identifier#getAuthority() authority}, or {@code null}
      * if no identifier was found.
@@ -219,8 +229,8 @@ public class IdentifierMapAdapter extend
     }
 
     /**
-     * Removes all identifiers associated with the given
-     * {@linkplain Identifier#getAuthority() authority}.
+     * Removes all identifiers associated with the given {@linkplain Identifier#getAuthority() authority}.
+     * The default implementation delegates to {@link #put(Citation, String)} with a {@code null} value.
      *
      * @param  authority The authority to search, which should be an instance of {@link Citation}.
      * @return The code of the identifier for the given authority, or {@code null} if none.
@@ -238,11 +248,15 @@ public class IdentifierMapAdapter extend
      * first entry, so it can be find by the {@code get} method.
      *
      * @param  authority The authority for which to set the code.
-     * @param  code The new code for the given authority.
+     * @param  code The new code for the given authority, or {@code null} for removing the entry.
      * @return The previous code for the given authority, or {@code null} if none.
+     * @throws IdentifierAlreadyBoundException If this map expects unique identifiers for the
+     *         given authority, and the given value is already associated to another object.
      */
     @Override
-    public String put(final Citation authority, final String code) throws UnsupportedOperationException {
+    public String put(final Citation authority, final String code)
+            throws IdentifierAlreadyBoundException, UnsupportedOperationException
+    {
         ArgumentChecks.ensureNonNull("authority", authority);
         String old = null;
         final Iterator<? extends Identifier> it = identifiers.iterator();
@@ -275,7 +289,9 @@ public class IdentifierMapAdapter extend
      * Sets the identifier associated with the given authority, and returns the previous value.
      */
     @Override
-    public <T> T putSpecialized(final IdentifierSpace<T> authority, final T value) throws UnsupportedOperationException {
+    public <T> T putSpecialized(final IdentifierSpace<T> authority, final T value)
+            throws IdentifierAlreadyBoundException, UnsupportedOperationException
+    {
         ArgumentChecks.ensureNonNull("authority", authority);
         T old = null;
         final Iterator<? extends Identifier> it = identifiers.iterator();
@@ -520,10 +536,19 @@ public class IdentifierMapAdapter extend
      * Overrides the string representation in order to use only the authority title as keys.
      * We do that because the string representations of {@code DefaultCitation} objects are
      * very big.
+     *
+     * <p>String examples:</p>
+     * <ul>
+     *   <li>{gml:id=“myID”}</li>
+     *   <li>{gco:uuid=“42924124-032a-4dfe-b06e-113e3cb81cf0”}</li>
+     *   <li>{xlink:href=“http://www.mydomain.org/myHREF”}</li>
+     * </ul>
+     *
+     * @see SpecializedIdentifier#toString()
      */
     @Override
     public String toString() {
-	final StringBuilder buffer = new StringBuilder(100).append('{');
+	final StringBuilder buffer = new StringBuilder(50).append('{');
 	for (final Entry<Citation,String> entry : entrySet()) {
 	    if (buffer.length() != 1) {
                 buffer.append(", ");

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapWithSpecialCases.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapWithSpecialCases.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapWithSpecialCases.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/IdentifierMapWithSpecialCases.java Wed Dec 12 13:38:18 2012
@@ -18,10 +18,12 @@ package org.apache.sis.internal.jaxb;
 
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.UUID;
 import java.util.Collection;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.apache.sis.xml.IdentifierSpace;
+import org.apache.sis.xml.IdentifierAlreadyBoundException;
 import org.apache.sis.xml.XLink;
 
 // Related to JDK7
@@ -30,40 +32,53 @@ import org.apache.sis.internal.util.Obje
 
 /**
  * A map of identifiers which handles some identifiers in a special way.
- * The identifiers for the following authorities are handled in a special way.
- * See usages of {@link #specialCase(Object)} for spotting the code where
- * a special handling is applied.
+ * The identifiers for the following authorities are handled in a special way:
  *
  * <ul>
- *   <li>{@link IdentifierSpace#HREF}, handled as a shortcut to {@link XLink#getHRef()}.</li>
+ *   <li>{@link IdentifierSpace#HREF}: handled as a shortcut to {@link XLink#getHRef()}.</li>
+ *   <li>{@link IdentifierSpace#UUID}: {@code put} operations register the UUID in a shared map.</li>
  * </ul>
  *
+ * See usages of {@link #specialCase(Object)} for identifying the code locations where a special
+ * handling is applied.
+ *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-3.19)
  * @version 0.3
  * @module
  */
-final class IdentifierMapWithSpecialCases extends IdentifierMapAdapter {
+public final class IdentifierMapWithSpecialCases extends IdentifierMapAdapter {
     /**
      * For cross-version compatibility.
      */
     private static final long serialVersionUID = 5139573827448780289L;
 
     /**
+     * The object being referenced by the identifiers, or {@code null} if not applicable.
+     */
+    private final Object referent;
+
+    /**
      * Creates a new map which will be a view over the given identifiers.
      *
      * @param identifiers The identifiers to wrap in a map view.
+     * @param referent    The object being referenced by the identifiers.
      */
-    public IdentifierMapWithSpecialCases(final Collection<Identifier> identifiers) {
+    public IdentifierMapWithSpecialCases(final Collection<Identifier> identifiers, final Object referent) {
         super(identifiers);
+        this.referent = referent;
     }
 
     /**
      * If the given authority is a special case, returns its {@link NonMarshalledAuthority}
      * integer enum. Otherwise returns -1. See javadoc for more information about special cases.
+     *
+     * @param authority A {@link Citation} constant. The type is relaxed to {@code Object}
+     *        because the signature of some {@code Map} methods are that way.
      */
     private static int specialCase(final Object authority) {
         if (authority == IdentifierSpace.HREF) return NonMarshalledAuthority.HREF;
+        if (authority == IdentifierSpace.UUID) return NonMarshalledAuthority.UUID;
         // A future Apache SIS version may add more special cases here.
         return -1;
     }
@@ -91,19 +106,42 @@ final class IdentifierMapWithSpecialCase
      * object.
      */
     private URI setHRef(final URI href) {
-        super.putSpecialized(IdentifierSpace.HREF, null);
+        URI old = super.putSpecialized(IdentifierSpace.HREF, null);
         XLink link = super.getSpecialized(IdentifierSpace.XLINK);
         if (link != null) {
-            final URI old = link.getHRef();
+            if (old == null) {
+                old = link.getHRef();
+            }
             link.setHRef(href);
-            return old;
-        }
-        if (href != null) {
+        } else if (href != null) {
             link = new XLink();
             link.setHRef(href);
             super.putSpecialized(IdentifierSpace.XLINK, link);
         }
-        return null;
+        return old;
+    }
+
+    /**
+     * Sets the {@code "gco:uuid"} value, which may be null. This method stores the UUID-object
+     * association in a shared map, if no value existed previously.
+     *
+     * @param  uuid The UUID to assign to the object.
+     * @return The previous value, or {@code null} if none.
+     * @throws IdentifierAlreadyBoundException If the given identifier is already associated to another object.
+     */
+    private UUID setUUID(final UUID uuid) throws IdentifierAlreadyBoundException {
+        if (referent == null) {
+            return super.putSpecialized(IdentifierSpace.UUID, uuid);
+        }
+        if (uuid != null) {
+            UUIDs.bind(uuid, referent); // May throws IdentifierAlreadyBoundException
+        }
+        // Invoke 'put' only if UUIDs.bind(…) has been succesful.
+        final UUID old = super.putSpecialized(IdentifierSpace.UUID, uuid);
+        if (old != null && !old.equals(uuid)) {
+            UUIDs.unbind(old, referent);
+        }
+        return old;
     }
 
     /**
@@ -173,19 +211,40 @@ final class IdentifierMapWithSpecialCase
      * {@inheritDoc}
      */
     @Override
-    public String put(final Citation authority, final String code) throws UnsupportedOperationException {
+    public String put(final Citation authority, final String code)
+            throws IdentifierAlreadyBoundException, UnsupportedOperationException
+    {
+        final Exception exception;
         switch (specialCase(authority)) {
+            default: {
+                return super.put(authority, code);
+            }
             case NonMarshalledAuthority.HREF: {
-                try {
-                    final URI old = setHRef((code != null) ? new URI(code) : null);
-                    return (old != null) ? old.toString() : null;
+                URI id = null;
+                if (code != null) try {
+                    id = new URI(code);
                 } catch (URISyntaxException e) {
-                    // Do not log the exception, since it will be
-                    // reported by super.put(Citation, String).
+                    exception = e;
+                    break;
                 }
-                break;
+                final String old = getUnspecialized(authority);
+                id = setHRef(id);
+                return (id != null) ? id.toString() : old;
+            }
+            case NonMarshalledAuthority.UUID: {
+                UUID id = null;
+                if (code != null) try {
+                    id = UUID.fromString(code);
+                } catch (IllegalArgumentException e) {
+                    exception = e;
+                    break;
+                }
+                final String old = getUnspecialized(authority);
+                id = setUUID(id);
+                return (id != null) ? id.toString() : old;
             }
         }
+        SpecializedIdentifier.parseFailure(exception);
         return super.put(authority, code);
     }
 
@@ -194,12 +253,13 @@ final class IdentifierMapWithSpecialCase
      */
     @Override
     @SuppressWarnings("unchecked")
-    public <T> T putSpecialized(final IdentifierSpace<T> authority, final T value) throws UnsupportedOperationException {
+    public <T> T putSpecialized(final IdentifierSpace<T> authority, final T value)
+            throws IdentifierAlreadyBoundException, UnsupportedOperationException
+    {
         switch (specialCase(authority)) {
-            case NonMarshalledAuthority.HREF: {
-                return (T) setHRef((URI) value);
-            }
+            default: return super.putSpecialized(authority, value);
+            case NonMarshalledAuthority.HREF: return (T) setHRef((URI)  value);
+            case NonMarshalledAuthority.UUID: return (T) setUUID((UUID) value);
         }
-        return super.putSpecialized(authority, value);
     }
 }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/SpecializedIdentifier.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/SpecializedIdentifier.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/SpecializedIdentifier.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/SpecializedIdentifier.java Wed Dec 12 13:38:18 2012
@@ -139,7 +139,7 @@ public final class SpecializedIdentifier
      * This is considered a non-fatal error, because the parse method can fallback
      * on the generic {@link IdentifierMapEntry} in such cases.
      */
-    private static void parseFailure(final Exception e) {
+    static void parseFailure(final Exception e) {
         // IdentifierMap.put(Citation,String) is the public facade.
         Logging.recoverableException(IdentifierMap.class, "put", e);
     }
@@ -197,10 +197,13 @@ public final class SpecializedIdentifier
 
     /**
      * Returns a string representation of this identifier.
+     * Example: {@code Identifier[gco:uuid=“42924124-032a-4dfe-b06e-113e3cb81cf0”]}.
+     *
+     * @see IdentifierMapAdapter#toString()
      */
     @Override
     public String toString() {
-        final StringBuilder buffer = new StringBuilder("Identifier[");
+        final StringBuilder buffer = new StringBuilder(60).append("Identifier[");
         format(buffer, authority, getCode());
         return buffer.append(']').toString();
     }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/UUIDs.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/UUIDs.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/UUIDs.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/UUIDs.java Wed Dec 12 13:38:18 2012
@@ -19,6 +19,7 @@ package org.apache.sis.internal.jaxb;
 import java.util.UUID;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.collection.WeakValueHashMap;
+import org.apache.sis.xml.IdentifierAlreadyBoundException;
 
 
 /**
@@ -60,14 +61,33 @@ public final class UUIDs extends Static 
     /**
      * Keep a weak references to the given object for the given UUID.
      * If an object is already mapped to the given UUID, then the mapping is <strong>not</strong>
-     * modified and the currently mapped object is returned. The returned object may or may not be
-     * equals to the object given in argument to this method.
+     * modified. An exception is thrown instead.
      *
      * @param  uuid   The UUID to associate to the object.
      * @param  object The object to associate to the UUID.
-     * @return If an object is already mapped to the given UUID, that object. Otherwise {@code null}.
+     * @throws IdentifierAlreadyBoundException If the given identifier is already associated to another object.
      */
-    public static Object store(final UUID uuid, final Object object) {
-        return OBJECTS.putIfAbsent(uuid, object);
+    static void bind(final UUID uuid, final Object object) throws IdentifierAlreadyBoundException {
+        final Object old = OBJECTS.putIfAbsent(uuid, object);
+        if (old != null && old != object) {
+            throw new IdentifierAlreadyBoundException(null, uuid);
+        }
+    }
+
+    /**
+     * Removes the entry associated to the given UUID.
+     * If the given UUID is associated to another object than the given one,
+     * then this method does nothing.
+     *
+     * @param uuid   The UUID of the entry to remove from the map.
+     * @param object The object to remove from the map.
+     */
+    static void unbind(final UUID uuid, final Object object) {
+        synchronized (OBJECTS) {
+            final Object old = OBJECTS.remove(uuid);
+            if (old != null && old != object) { // Same work than ConcurrentMap.remove(Object, Object);
+                OBJECTS.put(uuid, old);
+            }
+        }
     }
 }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/package-info.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/package-info.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/package-info.java Wed Dec 12 13:38:18 2012
@@ -42,7 +42,7 @@
  * </ul>
  *
  * Classes prefixed by two letters, like {@code "GO_Decimal"}, are also wrappers around the actual
- * object to be marshalled. See the {@link org.geotoolkit.internal.jaxb.metadata} package for more
+ * object to be marshalled. See the {@link org.apache.sis.internal.jaxb.metadata} package for more
  * explanation about wrappers. Note that the two-letters prefixes used in this package (not to be
  * confused with the three-letters prefixes used in XML documents) are not defined by OGC/ISO
  * specifications; they are used only for consistency with current practice in

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/simple/SimpleCitation.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/simple/SimpleCitation.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/simple/SimpleCitation.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/simple/SimpleCitation.java Wed Dec 12 13:38:18 2012
@@ -29,7 +29,7 @@ import org.opengis.metadata.citation.Res
 import org.opengis.metadata.citation.Series;
 import org.opengis.util.InternationalString;
 
-import org.apache.sis.util.type.SimpleInternationalString;
+import org.apache.sis.util.iso.SimpleInternationalString;
 
 
 /**

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=1420668&r1=1420667&r2=1420668&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 Wed Dec 12 13:38:18 2012
@@ -23,7 +23,9 @@ import org.opengis.metadata.citation.Cit
 import org.opengis.util.InternationalString;
 import org.apache.sis.util.Static;
 
+import static org.apache.sis.util.CharSequences.equalsFiltered;
 import static org.apache.sis.util.CharSequences.trimWhitespaces;
+import static org.apache.sis.util.Characters.Filter.LETTERS_AND_DIGITS;
 
 
 /**
@@ -56,15 +58,16 @@ public final class Citations extends Sta
      * @param  collection The collection from which to get the iterator, or {@code null}.
      * @return The iterator over the given collection elements, or {@code null}.
      */
-    public static <E> Iterator<E> iterator(final Collection<E> collection) {
+    private static <E> Iterator<E> iterator(final Collection<E> collection) {
         return (collection != null && !collection.isEmpty()) ? collection.iterator() : null;
     }
 
     /**
      * Returns {@code true} if at least one {@linkplain Citation#getTitle() title} or
-     * {@linkplain Citation#getAlternateTitles alternate title} in {@code c1} is equal
-     * to a title or alternate title in {@code c2}. The comparison is case-insensitive
-     * and ignores leading and trailing spaces. The titles ordering is not significant.
+     * {@linkplain Citation#getAlternateTitles() alternate title} in {@code c1} is leniently
+     * equal to a title or alternate title in {@code c2}. The comparison is case-insensitive
+     * and ignores every character which is not a {@linkplain Character#isLetterOrDigit(int)
+     * letter or a digit}. The titles ordering is not significant.
      *
      * @param  c1 The first citation to compare, or {@code null}.
      * @param  c2 the second citation to compare, or {@code null}.
@@ -105,30 +108,29 @@ public final class Citations extends Sta
 
     /**
      * Returns {@code true} if the {@linkplain Citation#getTitle() title} or any
-     * {@linkplain Citation#getAlternateTitles alternate title} in the given citation
-     * matches the given string. The comparison is case-insensitive and ignores leading
-     * and trailing spaces.
+     * {@linkplain Citation#getAlternateTitles() alternate title} in the given citation
+     * matches the given string. The comparison is case-insensitive and ignores every character
+     * which is not a {@linkplain Character#isLetterOrDigit(int) letter or a digit}.
      *
      * @param  citation The citation to check for, or {@code null}.
      * @param  title The title or alternate title to compare, or {@code null}.
      * @return {@code true} if both arguments are non-null, and the title or alternate
      *         title matches the given string.
      */
-    public static boolean titleMatches(final Citation citation, String title) {
+    public static boolean titleMatches(final Citation citation, final CharSequence title) {
         if (citation != null && title != null) {
-            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 unlocalized = trimWhitespaces(candidate.toString(null));
-                    if (unlocalized != null && unlocalized.equalsIgnoreCase(title)) {
+                    final String unlocalized = candidate.toString(null);
+                    if (equalsFiltered(unlocalized, title, LETTERS_AND_DIGITS, true)) {
                         return true;
                     }
-                    final String localized = trimWhitespaces(candidate).toString();
-                    if (localized != unlocalized // Slight optimization for a common case.
-                            && (localized != null) && localized.equalsIgnoreCase(title))
+                    final String localized = candidate.toString();
+                    if (!Objects.equals(localized, unlocalized) // Slight optimization for a common case.
+                            && equalsFiltered(localized, title, LETTERS_AND_DIGITS, true))
                     {
                         return true;
                     }
@@ -147,7 +149,8 @@ public final class Citations extends Sta
     /**
      * Returns {@code true} if at least one {@linkplain Citation#getIdentifiers() identifier} in
      * {@code c1} is equal to an identifier in {@code c2}. The comparison is case-insensitive
-     * and ignores leading and trailing spaces. The identifier ordering is not significant.
+     * and ignores every character which is not a {@linkplain Character#isLetterOrDigit(int)
+     * letter or a digit}. The identifier ordering is not significant.
      *
      * <p>If (and <em>only</em> if) the citations do not contains any identifier, then this method
      * fallback on titles comparison using the {@link #titleMatches(Citation,Citation) titleMatches}
@@ -190,8 +193,8 @@ public final class Citations extends Sta
 
     /**
      * Returns {@code true} if any {@linkplain Citation#getIdentifiers() identifiers} in the given
-     * citation matches the given string. The comparison is case-insensitive and ignores leading
-     * and trailing spaces.
+     * citation matches the given string. The comparison is case-insensitive and ignores every
+     * character which is not a {@linkplain Character#isLetterOrDigit(int) letter or a digit}.
      *
      * <p>If (and <em>only</em> if) the citation does not contain any identifier, then this method
      * fallback on titles comparison using the {@link #titleMatches(Citation,String) titleMatches}
@@ -203,20 +206,16 @@ public final class Citations extends Sta
      * @return {@code true} if both arguments are non-null, and the title or alternate title
      *         matches the given string.
      */
-    public static boolean identifierMatches(final Citation citation, String identifier) {
+    public static boolean identifierMatches(final Citation citation, final CharSequence identifier) {
         if (citation != null && identifier != null) {
-            identifier = trimWhitespaces(identifier);
             final Iterator<? extends Identifier> identifiers = iterator(citation.getIdentifiers());
             if (identifiers == null) {
                 return titleMatches(citation, identifier);
             }
             while (identifiers.hasNext()) {
                 final Identifier id = identifiers.next();
-                if (id != null) {
-                    final String code = id.getCode();
-                    if (code != null && identifier.equalsIgnoreCase(trimWhitespaces(code))) {
-                        return true;
-                    }
+                if (id != null && equalsFiltered(identifier, id.getCode(), LETTERS_AND_DIGITS, true)) {
+                    return true;
                 }
             }
         }

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/LocalizedParseException.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/LocalizedParseException.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/LocalizedParseException.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/LocalizedParseException.java Wed Dec 12 13:38:18 2012
@@ -86,7 +86,7 @@ public final class LocalizedParseExcepti
      *
      * @param locale      The locale for {@link #getLocalizedMessage()}.
      * @param key         The resource key as one of the {@link Errors.Keys} constant.
-     * @param  text       The full text that {@code Format} failed to parse.
+     * @param text        The full text that {@code Format} failed to parse.
      * @param errorOffset The position where the error is found while parsing.
      */
     public LocalizedParseException(final Locale locale, final int key, final CharSequence text, final int errorOffset) {
@@ -98,7 +98,7 @@ public final class LocalizedParseExcepti
      * information. This convenience constructor creates a message of the kind "<cite>Can not
      * parse string "text" as an object of type 'type'</cite>".
      *
-     * @param  locale The locale for {@link ParseException#getLocalizedMessage()}.
+     * @param  locale The locale for {@link #getLocalizedMessage()}.
      * @param  type   The type of objects parsed by the {@link java.text.Format}.
      * @param  text   The full text that {@code Format} failed to parse.
      * @param  pos    Index of the {@linkplain ParsePosition#getIndex() first parsed character},

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=1420668&r1=1420667&r2=1420668&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 Wed Dec 12 13:38:18 2012
@@ -122,7 +122,7 @@ public abstract class CompoundFormat<T> 
      * <ul>
      *   <li>Format {@link Number}s using {@code toString()} instead than {@code NumberFormat}.</li>
      *   <li>Format {@link InternationalString}s using {@code toString(null)}. This has the desired
-     *       behavior at least with the {@linkplain org.apache.sis.util.type.DefaultInternationalString#toString(Locale)
+     *       behavior at least with the {@linkplain org.apache.sis.util.iso.DefaultInternationalString#toString(Locale)
      *       SIS implementation}.</li>
      * </ul>
      *

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/io/LineFormatter.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/io/LineFormatter.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/io/LineFormatter.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/io/LineFormatter.java Wed Dec 12 13:38:18 2012
@@ -140,7 +140,7 @@ public class LineFormatter extends Filte
      * stream before the non-ignorable one. Otherwise if whitespaces are followed by a line
      * separator, then they are discarded.
      */
-    private final StringBuilder buffer = new StringBuilder(16);
+    private final StringBuilder buffer = new StringBuilder();
 
     /**
      * The number of Java characters (not Unicode code points) in {@link #buffer},

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/Angle.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/Angle.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/Angle.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/measure/Angle.java Wed Dec 12 13:38:18 2012
@@ -199,7 +199,7 @@ public class Angle implements Comparable
      */
     @Override
     public String toString() {
-        StringBuffer buffer = new StringBuffer(16);
+        StringBuffer buffer = new StringBuffer();
         double m = Math.abs(θ);
         final boolean isSmall = m <= (1 / 3600E+3); // 1E-3 arc-second.
         if (isSmall || m > maximum()) {
@@ -281,7 +281,7 @@ public class Angle implements Comparable
             if (precision > 0) {
                 format.setMaximumWidth(precision);
             }
-            value = format.format(this, new StringBuffer(16), null).toString();
+            value = format.format(this, new StringBuffer(), null).toString();
         }
         org.apache.sis.internal.util.Utilities.formatTo(formatter, flags, width, value);
     }

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=1420668&r1=1420667&r2=1420668&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 Wed Dec 12 13:38:18 2012
@@ -559,7 +559,7 @@ scan:   for (int i=0; i<length;) {
      */
     private String toPattern(final char[] symbols, final int decimalSeparator) {
         char symbol = 0;
-        final StringBuilder buffer = new StringBuilder(12);
+        final StringBuilder buffer = new StringBuilder();
         for (int field=DEGREES_FIELD; field<=FRACTION_FIELD; field++) {
             final String previousSuffix;
             int width;
@@ -781,7 +781,7 @@ scan:   for (int i=0; i<length;) {
      * @return The formatted string.
      */
     public final String format(final double angle) {
-        return format(angle, new StringBuffer(20), null).toString();
+        return format(angle, new StringBuffer(), null).toString();
     }
 
     /**
@@ -1053,7 +1053,7 @@ scan:   for (int i=0; i<length;) {
      */
     @Override
     public AttributedCharacterIterator formatToCharacterIterator(final Object value) {
-        final StringBuffer buffer = new StringBuffer(20);
+        final StringBuffer buffer = new StringBuffer();
         final FormattedCharacterIterator it = new FormattedCharacterIterator(buffer);
         try {
             characterIterator = it;

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=1420668&r1=1420667&r2=1420668&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 Wed Dec 12 13:38:18 2012
@@ -43,6 +43,7 @@ import org.apache.sis.util.resources.Err
  *     {@link #ensurePositive(String, int) ensurePositive},
  *     {@link #ensureStrictlyPositive(String, int) ensureStrictlyPositive},
  *     {@link #ensureBetween(String, int, int, int) ensureBetween},
+ *     {@link #ensureSizeBetween(String, int, int, int) ensureBetween},
  *     {@link #ensureCanCast(String, Class, Object) ensureCanCast}.
  *   </td>
  * </tr><tr>
@@ -89,7 +90,7 @@ public final class ArgumentChecks extend
      * Makes sure that an argument is non-null. If the given {@code object} is null, then a
      * {@link NullArgumentException} is thrown with a localized message containing the given name.
      *
-     * @param  name The name of the argument to be checked. Used only in case an exception is thrown.
+     * @param  name The name of the argument to be checked. Used only if an exception is thrown.
      * @param  object The user argument to check against null value.
      * @throws NullArgumentException if {@code object} is null.
      */
@@ -102,21 +103,19 @@ public final class ArgumentChecks extend
     }
 
     /**
-     * Makes sure that an array element is non-null. If {@code array[index]} is null, then a
-     * {@link NullArgumentException} is thrown with a localized message containing the given name.
-     *
-     * @param  name The name of the argument to be checked. Used only in case an exception is thrown.
-     * @param  index Index of the element to check.
-     * @param  array The user argument to check against null element.
-     * @throws NullArgumentException if {@code array} or {@code array[index]} is null.
+     * Makes sure that an array element is non-null. If {@code element} is null, then a
+     * {@link NullArgumentException} is thrown with a localized message containing the
+     * given name and index.
+     *
+     * @param  name    The name of the argument to be checked. Used only if an exception is thrown.
+     * @param  index   The Index of the element to check in an array or a list. Used only if an exception is thrown.
+     * @param  element The array or list element to check against null null.
+     * @throws NullArgumentException if {@code element} is null.
      */
-    public static void ensureNonNull(final String name, final int index, final Object[] array)
+    public static void ensureNonNullElement(final String name, final int index, final Object element)
             throws NullArgumentException
     {
-        if (array == null) {
-            throw new NullArgumentException(Errors.format(Errors.Keys.NullArgument_1, name));
-        }
-        if (array[index] == null) {
+        if (element == null) {
             throw new NullArgumentException(Errors.format(
                     Errors.Keys.NullArgument_1, name + '[' + index + ']'));
         }
@@ -128,7 +127,7 @@ public final class ArgumentChecks extend
      * a {@linkplain CharSequence#length() length} equals to 0, then an {@link IllegalArgumentException}
      * is thrown.
      *
-     * @param  name The name of the argument to be checked. Used only in case an exception is thrown.
+     * @param  name The name of the argument to be checked. Used only if an exception is thrown.
      * @param  text The user argument to check against null value and empty sequences.
      * @throws NullArgumentException if {@code text} is null.
      * @throws IllegalArgumentException if {@code text} is empty.
@@ -210,7 +209,7 @@ public final class ArgumentChecks extend
      * @throws IndexOutOfBoundsException If the given [{@code lower} … {@code upper}]
      *         range is out of the sequence index range.
      *
-     * @see #ensureBetween(String, int, int, int)
+     * @see #ensureSizeBetween(String, int, int, int)
      */
     public static void ensureValidIndexRange(final int length, final int lower, final int upper) throws IndexOutOfBoundsException {
         if (lower < 0 || upper < lower || upper > length) {
@@ -413,13 +412,25 @@ public final class ArgumentChecks extend
 
     /**
      * Ensures that the given integer value is between the given bounds, inclusive.
+     * This is a general-purpose method for checking integer arguments.
+     * Note that the following specialized methods are provided for common kinds
+     * of integer range checks:
+     *
+     * <ul>
+     *   <li>{@link #ensureSizeBetween(String, int, int, int) ensureSizeBetween(…)}
+     *       if the {@code value} argument is a collection size or an array length.</li>
+     *   <li>{@link #ensureValidIndex(int, int) ensureValidIndex(…)} if the {@code value}
+     *       argument is an index in a list or an array.</li>
+     * </ul>
      *
-     * @param  name  The name of the argument to be checked. Used only in case an exception is thrown.
+     * @param  name  The name of the argument to be checked. Used only if an exception is thrown.
      * @param  min   The minimal value, inclusive.
      * @param  max   The maximal value, inclusive.
-     * @param  value The value to be tested.
+     * @param  value The user argument to check.
      * @throws IllegalArgumentException if the given value is not in the given range.
      *
+     * @see #ensureSizeBetween(String, int, int, int)
+     * @see #ensureValidIndex(int, int)
      * @see #ensureValidIndexRange(int, int, int)
      */
     public static void ensureBetween(final String name, final int min, final int max, final int value)
@@ -434,10 +445,10 @@ public final class ArgumentChecks extend
     /**
      * Ensures that the given long 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.
+     * @param  name  The name of the argument to be checked. Used only if an exception is thrown.
      * @param  min   The minimal value, inclusive.
      * @param  max   The maximal value, inclusive.
-     * @param  value The value to be tested.
+     * @param  value The user argument to check.
      * @throws IllegalArgumentException if the given value is not in the given range.
      */
     public static void ensureBetween(final String name, final long min, final long max, final long value)
@@ -452,10 +463,10 @@ public final class ArgumentChecks extend
     /**
      * Ensures that the given floating point 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.
+     * @param  name  The name of the argument to be checked. Used only if an exception is thrown.
      * @param  min   The minimal value, inclusive.
      * @param  max   The maximal value, inclusive.
-     * @param  value The value to be tested.
+     * @param  value The user argument to check.
      * @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)
@@ -471,10 +482,10 @@ public final class ArgumentChecks extend
     /**
      * Ensures that the given floating point 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.
+     * @param  name  The name of the argument to be checked. Used only if an exception is thrown.
      * @param  min   The minimal value, inclusive.
      * @param  max   The maximal value, inclusive.
-     * @param  value The value to be tested.
+     * @param  value The user argument to check.
      * @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)
@@ -488,10 +499,42 @@ public final class ArgumentChecks extend
     }
 
     /**
+     * Ensures that the given collection size of array length is between the given bounds, inclusive.
+     * This method performs the same check than {@link #ensureBetween(String, int, int, int)
+     * ensureBetween(…)}, but the error message is different in case of failure.
+     *
+     * @param  name  The name of the argument to be checked. Used only if an exception is thrown.
+     * @param  min   The minimal size (inclusive), or 0 if none.
+     * @param  max   The maximal size (inclusive), or {@link Integer#MAX_VALUE} if none.
+     * @param  size  The user collection size or array length to be checked.
+     * @throws IllegalArgumentException if the given value is not in the given range.
+     *
+     * @see #ensureBetween(String, int, int, int)
+     * @see #ensureValidIndexRange(int, int, int)
+     */
+    public static void ensureSizeBetween(final String name, final int min, final int max, final int size)
+            throws IllegalArgumentException
+    {
+        final String message;
+        if (size < min) {
+            if (min == 1) {
+                message = Errors.format(Errors.Keys.EmptyArgument_1, name);
+            } else {
+                message = Errors.format(Errors.Keys.InsufficientArgumentSize_3, name, min, size);
+            }
+        } else if (size > max) {
+            message = Errors.format(Errors.Keys.ExcessiveArgumentSize_3, name, max, size);
+        } else {
+            return;
+        }
+        throw new IllegalArgumentException(message);
+    }
+
+    /**
      * Ensures that the given direct position has the expected number of dimensions.
      * This method does nothing if the given direct position is null.
      *
-     * @param  name     The name of the argument to be checked. Used only in case an exception is thrown.
+     * @param  name     The name of the argument to be checked. Used only if an exception is thrown.
      * @param  expected The expected number of dimensions.
      * @param  position The direct position to check for its dimension, or {@code null}.
      * @throws MismatchedDimensionException If the given direct position is non-null and does

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=1420668&r1=1420667&r2=1420668&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 Wed Dec 12 13:38:18 2012
@@ -1130,7 +1130,7 @@ searchWordBreak:    while (true) {
     }
 
     /**
-     * Given a string in camel cases (typically a Java identifier), returns a string formatted
+     * Given a string in camel cases (typically an identifier), returns a string formatted
      * like an English sentence. This heuristic method performs the following steps:
      *
      * <ol>
@@ -1261,8 +1261,8 @@ searchWordBreak:    while (true) {
      * 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#isJavaIdentifierPart(int) java identifier
-     * part} (including spaces).
+     * character which is not a {@linkplain Character#isUnicodeIdentifierPart(int) Unicode
+     * identifier part} (including spaces).
      *
      * <p><b>Examples:</b> given {@code "northEast"}, this method returns {@code "NE"}.
      * Given {@code "Open Geospatial Consortium"}, this method returns {@code "OGC"}.</p>
@@ -1271,18 +1271,19 @@ searchWordBreak:    while (true) {
      * @return The acronym, or {@code null} if the given text was null.
      */
     public static CharSequence camelCaseToAcronym(CharSequence text) {
-        if (text != null && !isUpperCase(text = trimWhitespaces(text))) {
+        text = trimWhitespaces(text);
+        if (text != null && !isUpperCase(text, 0, text.length())) {
             final int length = text.length();
             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);
                 if (wantChar) {
-                    if (isJavaIdentifierStart(c)) {
+                    if (isUnicodeIdentifierStart(c)) {
                         buffer.appendCodePoint(c);
                         wantChar = false;
                     }
-                } else if (!isJavaIdentifierPart(c) || c == '_') {
+                } else if (!isUnicodeIdentifierPart(c) || c == '_') {
                     wantChar = true;
                 } else if (Character.isUpperCase(c)) {
                     // Test for mixed-case (e.g. "northEast").
@@ -1411,7 +1412,7 @@ cmp:    while (ia < lga) {
      * <p>This method is used for identifying character strings that are likely to be code
      * like {@code "UTF-8"} or {@code "ISO-LATIN-1"}.</p>
      *
-     * @see #isJavaIdentifier(CharSequence)
+     * @see #isUnicodeIdentifier(CharSequence)
      */
     private static boolean isCode(final CharSequence identifier) {
         for (int i=identifier.length(); --i>=0;) {
@@ -1426,28 +1427,28 @@ cmp:    while (ia < lga) {
     }
 
     /**
-     * Returns {@code true} if the given identifier is a legal Java identifier.
+     * 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#isJavaIdentifierStart(int) Java
-     * identifier start} and all remaining characters (if any) are
-     * {@linkplain Character#isJavaIdentifierPart(int) Java identifier parts}.
+     * the first character is a {@linkplain Character#isUnicodeIdentifierStart(int)
+     * Unicode identifier start} and all remaining characters (if any) are
+     * {@linkplain Character#isUnicodeIdentifierPart(int) Unicode identifier parts}.
      *
      * @param identifier The character sequence to test.
-     * @return {@code true} if the given character sequence is a legal Java identifier.
+     * @return {@code true} if the given character sequence is a legal Unicode identifier.
      * @throws NullPointerException if the argument is null.
      */
-    public static boolean isJavaIdentifier(final CharSequence identifier) {
+    public static boolean isUnicodeIdentifier(final CharSequence identifier) {
         final int length = identifier.length();
         if (length == 0) {
             return false;
         }
         int c = codePointAt(identifier, 0);
-        if (!isJavaIdentifierStart(c)) {
+        if (!isUnicodeIdentifierStart(c)) {
             return false;
         }
         for (int i=0; (i += charCount(c)) < length;) {
             c = codePointAt(identifier, i);
-            if (!isJavaIdentifierPart(c)) {
+            if (!isUnicodeIdentifierPart(c)) {
                 return false;
             }
         }
@@ -1467,14 +1468,7 @@ cmp:    while (ia < lga) {
      *
      * @see String#toUpperCase()
      */
-    static boolean isUpperCase(final CharSequence text) {
-        return isUpperCase(text, 0, text.length());
-    }
-
-    /**
-     * Same as {@link #isUpperCase(CharSequence)}, but on a sub-sequence.
-     */
-    private static boolean isUpperCase(final CharSequence text, int lower, final int upper) {
+    static boolean isUpperCase(final CharSequence text, int lower, final int upper) {
         while (lower < upper) {
             final int c = codePointAt(text, lower);
             if (!Character.isUpperCase(c)) {
@@ -1486,6 +1480,71 @@ cmp:    while (ia < lga) {
     }
 
     /**
+     * Returns {@code true} if the given texts are equal, optionally ignoring case and filtered-out
+     * characters. This method is sometime used for comparing identifiers in a lenient way.
+     *
+     * <p><b>Example:</b> the following call compares the two strings ignoring case and any
+     * characters which are not {@linkplain Character#isLetterOrDigit(int) letter or digit}.
+     * In particular, spaces and punctuation characters like {@code '_'} and {@code '-'} are
+     * ignored:</p>
+     *
+     * {@preformat java
+     *     assert equals("WGS84", "WGS_84", Characters.Filter.LETTERS_AND_DIGITS, true) == true;
+     * }
+     *
+     * @param  s1 The first string to compare, or {@code null}.
+     * @param  s2 The second string to compare, or {@code null}.
+     * @param  filter The subset of characters to compare, or {@code null} for comparing all characters.
+     * @param  ignoreCase {@code true} for comparing cases, or {@code false} for requiring exact match.
+     * @return {@code true} if or if both arguments are {@code null} or if the two given texts are equal,
+     *         optionally ignoring case and filtered-out characters.
+     */
+    public static boolean equalsFiltered(final CharSequence s1, final CharSequence s2,
+            final Characters.Filter filter, final boolean ignoreCase)
+    {
+        if (s1 == s2) {
+            return true;
+        }
+        if (s1 == null || s2 == null) {
+            return false;
+        }
+        if (filter == null) {
+            return ignoreCase ? equalsIgnoreCase(s1, s2) : equals(s1, s2);
+        }
+        final int lg1 = s1.length();
+        final int lg2 = s2.length();
+        int i2 = 0, n;
+        for (int i1=0; i1<lg1; i1+=n) {
+            int c1 = codePointAt(s1, i1);
+            n = charCount(c1);
+            if (filter.contains(c1)) {
+                // Fetch the next significant character from the second string.
+                int c2;
+                do {
+                    if (i2 >= lg2) {
+                        return false; // The first string has more significant characters than expected.
+                    }
+                    c2 = codePointAt(s2, i2);
+                    i2 += charCount(c2);
+                } while (!filter.contains(c2));
+
+                // Compare the characters in the same way than String.equalsIgnoreCase(String).
+                if (c1 != c2 && !(ignoreCase && equalsIgnoreCase(c1, c2))) {
+                    return false;
+                }
+            }
+        }
+        while (i2 < lg2) {
+            final int s = codePointAt(s2, i2);
+            if (filter.contains(s)) {
+                return false; // The first string has less significant characters than expected.
+            }
+            i2 += charCount(s);
+        }
+        return true;
+    }
+
+    /**
      * Returns {@code true} if the given code points are equal, ignoring case.
      * This method implements the same comparison algorithm than String#equalsIgnoreCase(String).
      *
@@ -1743,9 +1802,9 @@ cmp:    while (ia < lga) {
      *
      * <ul>
      *   <li>If <var>c</var> is a
-     *       {@linkplain Character#isJavaIdentifierStart(int) Java identifier start},
+     *       {@linkplain Character#isUnicodeIdentifierStart(int) Unicode identifier start},
      *       then any following characters that are
-     *       {@linkplain Character#isJavaIdentifierPart(int) Java identifier part}.</li>
+     *       {@linkplain Character#isUnicodeIdentifierPart(int) Unicode identifier part}.</li>
      *   <li>Otherwise any character for which {@link Character#getType(int)} returns
      *       the same value than for <var>c</var>.</li>
      * </ul>
@@ -1774,8 +1833,8 @@ cmp:    while (ia < lga) {
         /*
          * Advance over all characters "of the same type".
          */
-        if (isJavaIdentifierStart(c)) {
-            while (upper<length && isJavaIdentifierPart(c = codePointAt(text, upper))) {
+        if (isUnicodeIdentifierStart(c)) {
+            while (upper<length && isUnicodeIdentifierPart(c = codePointAt(text, upper))) {
                 upper += charCount(c);
             }
         } else {

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Characters.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Characters.java?rev=1420668&r1=1420667&r2=1420668&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Characters.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Characters.java Wed Dec 12 13:38:18 2012
@@ -16,6 +16,8 @@
  */
 package org.apache.sis.util;
 
+import org.apache.sis.util.resources.Errors;
+
 
 /**
  * Static methods working on {@code char} values, and some character constants.
@@ -225,4 +227,195 @@ public final class Characters extends St
         }
         return c;
     }
+
+
+
+
+    /**
+     * Subsets of Unicode characters identified by their general category.
+     * The categories are identified by constants defined in the {@link Character} class, like
+     * {@link Character#LOWERCASE_LETTER     LOWERCASE_LETTER},
+     * {@link Character#UPPERCASE_LETTER     UPPERCASE_LETTER},
+     * {@link Character#DECIMAL_DIGIT_NUMBER DECIMAL_DIGIT_NUMBER} and
+     * {@link Character#SPACE_SEPARATOR      SPACE_SEPARATOR}.
+     *
+     * <p>An instance of this class can be obtained from an enumeration of character types
+     * using the {@link #forTypes(byte[])} method, or using one of the constants predefined
+     * in this class. Then, Unicode characters can be tested for inclusion in the subset by
+     * calling the {@link #contains(int)} method.</p>
+     *
+     * @author  Martin Desruisseaux (Geomatys)
+     * @since   0.3
+     * @version 0.3
+     * @module
+     *
+     * @see java.lang.Character.Subset
+     * @see Character#getType(int)
+     */
+    public static class Filter extends Character.Subset {
+        /*
+         * This class can not easily be Serializable, because the parent class is not Serializable
+         * and does not define a no-argument constructor.  We could workaround with a writeReplace
+         * method - waiting to see if there is a real need for that.
+         */
+
+        /**
+         * The subset of all characters for which {@link Character#isLetterOrDigit(int)}
+         * returns {@code true}. This subset includes the following general categories:
+         * {@link Character#LOWERCASE_LETTER},
+         * {@link Character#UPPERCASE_LETTER     UPPERCASE_LETTER},
+         * {@link Character#TITLECASE_LETTER     TITLECASE_LETTER},
+         * {@link Character#MODIFIER_LETTER      MODIFIER_LETTER},
+         * {@link Character#OTHER_LETTER         OTHER_LETTER} and
+         * {@link Character#DECIMAL_DIGIT_NUMBER DECIMAL_DIGIT_NUMBER}.
+         */
+        public static final Filter LETTERS_AND_DIGITS = new LettersAndDigits();
+
+        /**
+         * The subset of all characters for which {@link Character#isUnicodeIdentifierPart(int)}
+         * returns {@code true}, excluding {@linkplain Character#isIdentifierIgnorable(int)
+         * ignorable} characters. This subset includes all the {@link #LETTERS_AND_DIGITS}
+         * categories with the addition of the following ones:
+         * {@link Character#LETTER_NUMBER},
+         * {@link Character#CONNECTOR_PUNCTUATION CONNECTOR_PUNCTUATION},
+         * {@link Character#NON_SPACING_MARK NON_SPACING_MARK} and
+         * {@link Character#COMBINING_SPACING_MARK COMBINING_SPACING_MARK}.
+         */
+        public static final Filter UNICODE_IDENTIFIER = new UnicodeIdentifier();
+
+        /**
+         * A bitmask of character types in this subset.
+         */
+        private final long types;
+
+        /**
+         * Creates a new subset of the given name.
+         *
+         * @param name  The subset name.
+         * @param types A bitmask of character types.
+         */
+        Filter(final String name, final long types) {
+            super(name);
+            this.types = types;
+        }
+
+        /**
+         * Returns {@code true} if this subset contains the given Unicode character.
+         *
+         * @param  codePoint The Unicode character, as a code point value.
+         * @return {@code true} if this subset contains the given character.
+         */
+        public boolean contains(final int codePoint) {
+            return containsType(Character.getType(codePoint));
+        }
+
+        /**
+         * Returns {@code true} if this subset contains the characters of the given type.
+         * The given type shall be one of the {@link Character} constants like
+         * {@link Character#LOWERCASE_LETTER     LOWERCASE_LETTER},
+         * {@link Character#UPPERCASE_LETTER     UPPERCASE_LETTER},
+         * {@link Character#DECIMAL_DIGIT_NUMBER DECIMAL_DIGIT_NUMBER} or
+         * {@link Character#SPACE_SEPARATOR      SPACE_SEPARATOR}.
+         *
+         * @param  type One of the {@link Character} constants.
+         * @return {@code true} if this subset contains the characters of the given type.
+         *
+         * @see Character#getType(int)
+         */
+        public final boolean containsType(final int type) {
+            return (type >= 0) && (type < Long.SIZE) && (types & (1L << type)) != 0;
+        }
+
+        /**
+         * Returns a subset representing the union of all Unicode characters of the given types.
+         *
+         * @param  types The character types, as {@link Character} constants.
+         * @return The subset of Unicode characters of the given type.
+         *
+         * @see Character#LOWERCASE_LETTER
+         * @see Character#UPPERCASE_LETTER
+         * @see Character#DECIMAL_DIGIT_NUMBER
+         * @see Character#SPACE_SEPARATOR
+         */
+        public static Filter forTypes(final byte... types) {
+            long mask = 0;
+            for (int i=0; i<types.length; i++) {
+                final int type = types[i];
+                if (type < 0 || type >= Long.SIZE) {
+                    throw new IllegalArgumentException(Errors.format(
+                            Errors.Keys.IllegalArgumentValue_2, "types[" + i + ']', type));
+                }
+                mask |= (1L << type);
+            }
+predefined: for (int i=0; ; i++) {
+                final Filter candidate;
+                switch (i) {
+                    case 0:  candidate = LETTERS_AND_DIGITS; break;
+                    case 1:  candidate = UNICODE_IDENTIFIER; break;
+                    default: break predefined;
+                }
+                if (mask == candidate.types) {
+                    return candidate;
+                }
+            }
+            return new Filter("Filter", mask);
+        }
+    }
+
+    /**
+     * Implementation of the {@link Filter#LETTERS_AND_DIGITS} constant.
+     */
+    private static final class LettersAndDigits extends Filter {
+        /**
+         * Creates the {@link Filter#LETTERS_AND_DIGITS} singleton instance.
+         */
+        LettersAndDigits() {
+            super("LETTERS_AND_DIGITS",
+                      (1L << Character.LOWERCASE_LETTER)
+                    | (1L << Character.UPPERCASE_LETTER)
+                    | (1L << Character.TITLECASE_LETTER)
+                    | (1L << Character.MODIFIER_LETTER)
+                    | (1L << Character.OTHER_LETTER)
+                    | (1L << Character.DECIMAL_DIGIT_NUMBER));
+        }
+
+        /**
+         * Returns {@code true} if this subset contains the given Unicode character.
+         */
+        @Override
+        public boolean contains(final int codePoint) {
+            return Character.isLetterOrDigit(codePoint);
+        }
+    }
+
+    /**
+     * Implementation of the {@link Filter#UNICODE_IDENTIFIER} constant.
+     */
+    private static final class UnicodeIdentifier extends Filter {
+        /**
+         * Creates the {@link Filter#LETTERS_AND_DIGITS} singleton instance.
+         */
+        UnicodeIdentifier() {
+            super("UNICODE_IDENTIFIER",
+                      (1L << Character.LOWERCASE_LETTER)
+                    | (1L << Character.UPPERCASE_LETTER)
+                    | (1L << Character.TITLECASE_LETTER)
+                    | (1L << Character.MODIFIER_LETTER)
+                    | (1L << Character.OTHER_LETTER)
+                    | (1L << Character.DECIMAL_DIGIT_NUMBER)
+                    | (1L << Character.LETTER_NUMBER)
+                    | (1L << Character.CONNECTOR_PUNCTUATION)
+                    | (1L << Character.NON_SPACING_MARK)
+                    | (1L << Character.COMBINING_SPACING_MARK));
+        }
+
+        /**
+         * Returns {@code true} if this subset contains the given Unicode character.
+         */
+        @Override
+        public boolean contains(final int codePoint) {
+            return Character.isUnicodeIdentifierPart(codePoint) &&
+                  !Character.isIdentifierIgnorable(codePoint);
+        }
+    }
 }



Mime
View raw message