sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1686268 [3/4] - in /sis/branches/JDK7: ./ core/sis-feature/src/main/java/org/apache/sis/feature/ core/sis-feature/src/test/java/org/apache/sis/feature/ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src...
Date Thu, 18 Jun 2015 16:49:27 GMT
Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/WKTFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/WKTFormat.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/WKTFormat.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/WKTFormat.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -21,6 +21,8 @@ import java.util.Locale;
 import java.util.TimeZone;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.Collections;
+import java.util.List;
 import java.io.IOException;
 import java.text.Format;
 import java.text.NumberFormat;
@@ -31,6 +33,7 @@ import java.text.ParseException;
 import javax.measure.unit.Unit;
 import javax.measure.unit.UnitFormat;
 import org.opengis.util.Factory;
+import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.IdentifiedObject;
 import org.apache.sis.io.CompoundFormat;
@@ -76,9 +79,15 @@ import org.apache.sis.util.resources.Err
  * PROJECTION[</code> <i>…etc…</i> <code>]]");</code></blockquote>
  * </div>
  *
- * <div class="section">Thread safety</div>
- * {@code WKTFormat}s are not synchronized. It is recommended to create separated format instances for each thread.
- * If multiple threads access a {@code WKTFormat} concurrently, it must be synchronized externally.
+ * <div class="section">Limitations</div>
+ * <ul>
+ *   <li>Instances of this class are not synchronized for multi-threading.
+ *       It is recommended to create separated format instances for each thread.
+ *       If multiple threads access a {@code WKTFormat} concurrently, it must be synchronized externally.</li>
+ *   <li>Serialized objects of this class are not guaranteed to be compatible with future Apache SIS releases.
+ *       Serialization support is appropriate for short term storage or RMI between applications running the
+ *       same version of Apache SIS.</li>
+ * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Rémi Eve (IRD)
@@ -178,7 +187,7 @@ public class WKTFormat extends CompoundF
     /**
      * The parser. Will be created when first needed.
      */
-    private transient Parser parser;
+    private transient AbstractParser parser;
 
     /**
      * The factories needed by the parser. Will be created when first needed.
@@ -186,9 +195,15 @@ public class WKTFormat extends CompoundF
     private transient Map<Class<?>,Factory> factories;
 
     /**
+     * The warning produced by the last parsing or formatting operation, or {@code null} if none.
+     *
+     * @see #getWarnings()
+     */
+    private transient Warnings warnings;
+
+    /**
      * Creates a format for the given locale and timezone. The given locale will be used for
-     * {@link org.opengis.util.InternationalString} localization; this is <strong>not</strong>
-     * the locale for number format.
+     * {@link InternationalString} localization; this is <strong>not</strong> the locale for number format.
      *
      * @param locale   The locale for the new {@code Format}, or {@code null} for {@code Locale.ROOT}.
      * @param timezone The timezone, or {@code null} for UTC.
@@ -208,7 +223,7 @@ public class WKTFormat extends CompoundF
      *   <li>{@link java.util.Locale.Category#FORMAT}: the value of {@link Symbols#getLocale()},
      *       normally fixed to {@link Locale#ROOT}, used for number formatting.</li>
      *   <li>{@link java.util.Locale.Category#DISPLAY}: the {@code locale} given at construction time,
-     *       used for {@link org.opengis.util.InternationalString} localization.</li>
+     *       used for {@link InternationalString} localization.</li>
      * </ul>
      *
      * @param  category The category for which a locale is desired.
@@ -499,16 +514,26 @@ public class WKTFormat extends CompoundF
      */
     @Override
     public Object parse(final CharSequence text, final ParsePosition pos) throws ParseException {
+        warnings = null;
+        ArgumentChecks.ensureNonNull("text", text);
+        ArgumentChecks.ensureNonNull("pos",  pos);
+        AbstractParser parser = this.parser;
         if (parser == null) {
             if (factories == null) {
                 factories = new HashMap<>();
             }
-            parser = new GeodeticObjectParser(symbols,
+            this.parser = parser = new GeodeticObjectParser(symbols,
                     (NumberFormat) getFormat(Number.class),
                     (DateFormat)   getFormat(Date.class),
-                    convention, false, getLocale(Locale.Category.DISPLAY), factories);
+                    (UnitFormat)   getFormat(Unit.class),
+                    convention, getLocale(), factories);
+        }
+        Object object = null;
+        try {
+            return object = parser.parseObject(text.toString(), pos);
+        } finally {
+            warnings = parser.getAndClearWarnings(object);
         }
-        return parser.parseObject(text.toString(), pos);
     }
 
     /**
@@ -524,10 +549,11 @@ public class WKTFormat extends CompoundF
      * @param  toAppendTo Where the text is to be appended.
      * @throws IOException If an error occurred while writing to {@code toAppendTo}.
      *
-     * @see #getWarning()
+     * @see FormattableObject#toWKT()
      */
     @Override
     public void format(final Object object, final Appendable toAppendTo) throws IOException {
+        warnings = null;
         ArgumentChecks.ensureNonNull("object",     object);
         ArgumentChecks.ensureNonNull("toAppendTo", toAppendTo);
         /*
@@ -555,13 +581,20 @@ public class WKTFormat extends CompoundF
             this.formatter = formatter;
         }
         final boolean valid;
+        final InternationalString warning;
         try {
             formatter.setBuffer(buffer);
             valid = formatter.appendElement(object) || formatter.appendValue(object);
         } finally {
+            warning = formatter.getErrorMessage();  // Must be saved before formatter.clear() is invoked.
             formatter.setBuffer(null);
             formatter.clear();
         }
+        if (warning != null) {
+            warnings = new Warnings(getLocale(), (byte) 0, Collections.<String, List<String>>emptyMap());
+            warnings.add(warning, formatter.getErrorCause(), null);
+            warnings.setRoot(object);
+        }
         if (!valid) {
             throw new ClassCastException(Errors.format(
                     Errors.Keys.IllegalArgumentClass_2, "object", object.getClass()));
@@ -594,13 +627,34 @@ public class WKTFormat extends CompoundF
     }
 
     /**
-     * If a warning occurred during the last WKT {@linkplain #format(Object, Appendable) formatting}, returns
-     * the warning. Otherwise returns {@code null}. The warning is cleared every time a new object is formatted.
+     * If warnings occurred during the last WKT {@linkplain #parse(CharSequence, ParsePosition) parsing} or
+     * {@linkplain #format(Object, Appendable) formatting}, returns the warnings. Otherwise returns {@code null}.
+     * The warnings are cleared every time a new object is parsed or formatted.
+     *
+     * @return The warnings of the last parsing of formatting operation, or {@code null} if none.
+     *
+     * @since 0.6
+     */
+    public Warnings getWarnings() {
+        final Warnings w = warnings;
+        if (w != null) {
+            w.publish();
+        }
+        return w;
+    }
+
+    /**
+     * If a warning occurred during the last WKT {@linkplain #parse(CharSequence, ParsePosition) parsing} or
+     * {@linkplain #format(Object, Appendable) formatting}, returns the warning. Otherwise returns {@code null}.
+     * The warning is cleared every time a new object is parsed or formatted.
      *
      * @return The last warning, or {@code null} if none.
+     *
+     * @deprecated Replaced by {@link #getWarnings()}.
      */
+    @Deprecated
     public String getWarning() {
-        return (formatter != null) ? formatter.getErrorMessage() : null;
+        return (warnings != null) ? warnings.toString() : null;
     }
 
     /**
@@ -612,6 +666,8 @@ public class WKTFormat extends CompoundF
     public WKTFormat clone() {
         final WKTFormat clone = (WKTFormat) super.clone();
         clone.formatter = null; // Do not share the formatter.
+        clone.parser    = null;
+        clone.warnings  = null;
         return clone;
     }
 }

Copied: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Warnings.java (from r1686266, sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Warnings.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Warnings.java?p2=sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Warnings.java&p1=sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Warnings.java&r1=1686266&r2=1686268&rev=1686268&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Warnings.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Warnings.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -202,7 +202,9 @@ public final class Warnings implements L
      */
     final void publish() {
         if (!published) {
-            ignoredElements = ignoredElements.isEmpty() ? Collections.emptyMap() : new LinkedHashMap<>(ignoredElements);
+            ignoredElements = ignoredElements.isEmpty()
+                    ? Collections.<String, List<String>>emptyMap()
+                    : new LinkedHashMap<>(ignoredElements);
             published = true;
         }
     }
@@ -238,7 +240,7 @@ public final class Warnings implements L
      * @return The non-fatal exceptions that occurred.
      */
     public Set<Exception> getExceptions() {
-        return (exceptionSources != null) ? exceptionSources.keySet() : Collections.emptySet();
+        return (exceptionSources != null) ? exceptionSources.keySet() : Collections.<Exception>emptySet();
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/package-info.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/package-info.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/package-info.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -17,21 +17,30 @@
 
 /**
  * <cite>Well Known Text</cite> (WKT) parsing and formatting.
- * This package implements the services provided by the {@link org.apache.sis.referencing.CRS#parseWKT(String)}
- * and {@link org.opengis.referencing.IdentifiedObject#toWKT()} convenience methods, with more control.
+ * This package implements the services provided by various convenience methods:
+ *
+ * <ul>
+ *   <li>{@link org.apache.sis.referencing.CRS#fromWKT(String)} (SIS parsing static method)</li>
+ *   <li>{@link org.opengis.referencing.crs.CRSFactory#createFromWKT(String)} (GeoAPI parsing method)</li>
+ *   <li>{@link org.opengis.referencing.operation.MathTransformFactory#createFromWKT(String)} (GeoAPI parsing method)</li>
+ *   <li>{@link org.opengis.referencing.IdentifiedObject#toWKT()} (GeoAPI formatting method)</li>
+ * </ul>
+ *
+ * However the {@link org.apache.sis.io.wkt.WKTFormat} class provided in this package gives more control.
  * For example this package allows to:
  *
  * <ul>
- *   <li>Format projection and parameters using the names of a chosen authority. For example the
- *       <cite>"Mercator (variant A)"</cite> projection is named {@code "Mercator_1SP"} by OGC 01-009
- *       and {@code "CT_Mercator"} by GeoTIFF.</li>
- *   <li>Format the elements with curly brackets instead than square ones.
+ *   <li>Format projection and parameters using the names of a chosen authority.
+ *       For example the <cite>"Mercator (variant A)"</cite> projection is named
+ *       {@code "Mercator_1SP"} by OGC 01-009 and {@code "CT_Mercator"} by GeoTIFF.</li>
+ *   <li>Format the elements with different quote characters or brackets style.
  *       For example both {@code ID["EPSG",4326]} and {@code ID("EPSG",4326)} are legal WKT.</li>
  *   <li>Format with a different indentation or format the whole WKT on a single line.</li>
  *   <li>Apply syntactic coloring on terminal supporting <cite>ANSI escape codes</cite>
  *       (a.k.a. ECMA-48, ISO/IEC 6429 and X3.64).</li>
- *   <li>Ignore the {@code AXIS[…]} elements at parsing time. This approach can be used as a way to force
- *       the (<var>longitude</var>, <var>latitude</var>) axes order.</li>
+ *   <li>Alter the parsing in a way compatible with non-standard (but commonly used) WKT.
+ *       For example some others softwares ignore the {@code AXIS[…]} elements at parsing time.</li>
+ *   <li>Report warnings that occurred during parsing or formatting.</li>
  * </ul>
  *
  * <div class="section">Referencing WKT</div>
@@ -56,11 +65,25 @@
  * provide their own, limited, WKT parsing and formatting services for the {@code BOX} and {@code POINT} elements.
  * A description for this WKT format can be found on <a href="http://en.wikipedia.org/wiki/Well-known_text">Wikipedia</a>.
  *
+ * <div class="section">Where to find WKT examples</div>
+ * An excellent source of well-formed WKT is the online <cite>EPSG Geodetic Parameter Registry</cite>.
+ * The WKT of many Coordinate Reference System object can be viewed using the pattern below
+ * (replace {@code 3395} by the EPSG code of the desired CRS):
+ *
+ * <blockquote><b>Example</b>: <cite>"WGS 84 / World Mercator"</cite>:
+ * <a href="http://epsg-registry.org/export.htm?wkt=urn:ogc:def:crs:EPSG::3395">http://epsg-registry.org/export.htm?wkt=urn:ogc:def:crs:EPSG::3395</a>
+ * </blockquote>
+ *
+ * Readers should be aware that some popular other sources of WKT are actually invalid,
+ * since many of them do not comply with EPSG definitions (especially on axis order).
+ * The above-cited EPSG registry is <strong>the</strong> authoritative source
+ * of CRS definitions in the EPSG namespace.
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Rémi Eve (IRD)
  * @author  Rueben Schulz (UBC)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  *
  * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a>

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -22,6 +22,7 @@ import javax.xml.bind.annotation.XmlRoot
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.util.InternationalString;
+import org.apache.sis.internal.util.Citations;
 
 
 /**
@@ -76,7 +77,7 @@ import org.opengis.util.InternationalStr
  * @author  Touraïvane (IRD)
  * @author  Cédric Briançon (Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.6
  * @module
  *
  * @see ImmutableIdentifier
@@ -139,15 +140,32 @@ public class DefaultIdentifier extends I
 
     /**
      * Creates an identifier initialized to the given authority and code.
+     * This constructor automatically initializes the {@linkplain #getCodeSpace() code space} to a value inferred
+     * from the given {@code authority}, if a suitable value can be found. This constructor proceeds by searching
+     * for the first suitable property in the following list:
+     *
+     * <ol>
+     *   <li>The value of {@link org.apache.sis.xml.IdentifierSpace#getName()}.</li>
+     *   <li>A {@linkplain org.apache.sis.metadata.iso.citation.DefaultCitation#getIdentifiers() citation identifier}
+     *       which is a valid
+     *       {@linkplain org.apache.sis.util.CharSequences#isUnicodeIdentifier(CharSequence) unicode identifier}.</li>
+     *   <li>Only if the citation has no identifier, a citation title or
+     *       {@linkplain org.apache.sis.metadata.iso.citation.DefaultCitation#getAlternateTitles() alternate title}
+     *       which is a valid
+     *       {@linkplain org.apache.sis.util.CharSequences#isUnicodeIdentifier(CharSequence) unicode identifier}.</li>
+     * </ol>
      *
      * @param authority The organization or party responsible for definition and maintenance
      *                  of the code, or {@code null} if none.
      * @param code      The alphanumeric value identifying an instance in the namespace,
      *                  or {@code null} if none.
+     *
+     * @see org.apache.sis.metadata.iso.citation.Citations#getUnicodeIdentifier(Citation)
      */
     public DefaultIdentifier(final Citation authority, final String code) {
         this.authority = authority;
         this.code = code;
+        codeSpace = Citations.getCodeSpace(authority);
     }
 
     /**
@@ -197,6 +215,12 @@ public class DefaultIdentifier extends I
 
     /**
      * Returns the alphanumeric value identifying an instance in the namespace.
+     * The code is optionally from a controlled list or pattern.
+     *
+     * <div class="note"><b>Example:</b> {@code "4326"}.</div>
+     *
+     * The code is mandatory according ISO specification, but this {@code DefaultIdentifier}
+     * implementation does not enforce this restriction.
      *
      * @return Value identifying an instance in the namespace.
      */
@@ -218,6 +242,9 @@ public class DefaultIdentifier extends I
 
     /**
      * Returns the identifier or namespace in which the code is valid.
+     * This is often the {@linkplain #getAuthority() authority}'s abbreviation, but not necessarily.
+     *
+     * <div class="note"><b>Example:</b> {@code "EPSG"}.</div>
      *
      * @return The identifier code space, or {@code null} if none.
      *
@@ -246,6 +273,8 @@ public class DefaultIdentifier extends I
      * uses versions. When appropriate, the edition is identified by the effective date,
      * coded using ISO 8601 date format.
      *
+     * <div class="note"><b>Example:</b> the version of the underlying EPSG database.</div>
+     *
      * @return The version, or {@code null} if not available.
      */
     @Override
@@ -266,6 +295,8 @@ public class DefaultIdentifier extends I
     /**
      * Returns the natural language description of the meaning of the code value.
      *
+     * <div class="note"><b>Example:</b> "World Geodetic System 1984".</div>
+     *
      * @return The natural language description, or {@code null} if none.
      *
      * @since 0.5
@@ -288,8 +319,9 @@ public class DefaultIdentifier extends I
     }
 
     /**
-     * Organization or party responsible for definition and maintenance of the
-     * {@linkplain #getCode() code}.
+     * Organization or party responsible for definition and maintenance of the {@linkplain #getCode() code}.
+     * The organization's abbreviation is often the same than this identifier {@linkplain #getCodeSpace() code space},
+     * but not necessarily.
      *
      * @return The authority, or {@code null} if not available.
      */
@@ -300,8 +332,7 @@ public class DefaultIdentifier extends I
     }
 
     /**
-     * Sets the organization or party responsible for definition and maintenance of the
-     * {@linkplain #getCode() code}.
+     * Sets the organization or party responsible for definition and maintenance of the {@linkplain #getCode() code}.
      *
      * @param newValue The new authority.
      */

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicDescription.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicDescription.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicDescription.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultGeographicDescription.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -19,14 +19,26 @@ package org.apache.sis.metadata.iso.exte
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
+import org.opengis.util.InternationalString;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.extent.GeographicDescription;
 import org.apache.sis.metadata.iso.DefaultIdentifier;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.iso.Types;
 
 
 /**
  * Description of the geographic area using identifiers.
+ * The area is given by a {@linkplain #getGeographicIdentifier() geographic identifier},
+ * which may be a code in the codespace of some authority (for example an EPSG code).
+ * In addition, the geographic identifier can optionally have a
+ * {@linkplain DefaultIdentifier#getDescription() natural language description}.
+ *
+ * <div class="note"><b>Example:</b>
+ * a geographic area may be identified by the {@code 1731} code in the {@code EPSG} codespace.
+ * The natural language description for {@code EPSG:1731} can be <cite>“France – mainland north of 48.15°N”</cite>.
+ * </div>
  *
  * <p><b>Limitations:</b></p>
  * <ul>
@@ -41,7 +53,7 @@ import org.apache.sis.metadata.iso.Defau
  * @author  Touraïvane (IRD)
  * @author  Cédric Briançon (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.6
  * @module
  */
 @XmlType(name = "EX_GeographicDescription_Type")
@@ -64,16 +76,57 @@ public class DefaultGeographicDescriptio
     }
 
     /**
-     * Creates an inclusive geographic description initialized to the specified value.
+     * Creates an inclusive geographic description initialized to the given identifier.
      * This constructor sets the {@linkplain #getInclusion() inclusion} property to {@code true}.
      *
+     * <p><b>Usage note:</b> if the description is a sentence like “Netherlands offshore”, it may not be suitable
+     * for the {@code code} argument. Callers may consider using the {@linkplain DefaultIdentifier#getDescription()
+     * identifier description} as an alternative and keep the code for a more compact string (often a primary key).</p>
+     *
+     * <div class="note"><b>Example:</b>
+     * <code>new DefaultGeographicDescription({@link org.apache.sis.metadata.iso.citation.Citations#EPSG}, "1731")</code>
+     * can stand for <cite>“France – mainland north of 48.15°N”</cite>.</div>
+     *
      * @param authority The authority of the identifier code, or {@code null} if none.
      * @param code The identifier code used to represent a geographic area, or {@code null} if none.
      */
     public DefaultGeographicDescription(final Citation authority, final String code) {
         super(true);
         if (authority != null || code != null) {
-            this.geographicIdentifier = new DefaultIdentifier(authority, code);
+            geographicIdentifier = new DefaultIdentifier(authority, code);
+        }
+    }
+
+    /**
+     * Creates an inclusive geographic description initialized to the given natural language description.
+     * This constructor sets the {@linkplain #getInclusion() inclusion} property to {@code true} and the
+     * {@linkplain DefaultIdentifier#getCode() identifier code} to one of the following choices:
+     *
+     * <ul>
+     *   <li>the given {@code description} string if it is a valid
+     *       {@linkplain CharSequences#isUnicodeIdentifier(CharSequence) Unicode identifier},</li>
+     *   <li>otherwise an {@linkplain CharSequences#camelCaseToAcronym(CharSequence) acronym}
+     *       of the given {@code description}.</li>
+     * </ul>
+     *
+     * @param description The natural language description of the meaning of the code value, or {@code null} if none.
+     *
+     * @since 0.6
+     */
+    public DefaultGeographicDescription(final CharSequence description) {
+        super(true);
+        if (description != null) {
+            final DefaultIdentifier id = new DefaultIdentifier();
+            if (CharSequences.isUnicodeIdentifier(description)) {
+                id.setCode(description.toString());
+                if (description instanceof InternationalString) {
+                    id.setDescription((InternationalString) description);
+                }
+            } else {
+                id.setCode(CharSequences.camelCaseToAcronym(description).toString());
+                id.setDescription(Types.toInternationalString(description));
+            }
+            geographicIdentifier = id;
         }
     }
 
@@ -121,6 +174,14 @@ public class DefaultGeographicDescriptio
     /**
      * Returns the identifier used to represent a geographic area.
      *
+     * <div class="note"><b>Example:</b>
+     * an identifier with the following properties:
+     * <ul>
+     *   <li>the {@code "EPSG"} code space,</li>
+     *   <li>the {@code "1731"} code, and</li>
+     *   <li>the <cite>“France – mainland north of 48.15°N”</cite> description.</li>
+     * </ul></div>
+     *
      * @return The identifier used to represent a geographic area, or {@code null}.
      */
     @Override

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/Extents.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/Extents.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/Extents.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/Extents.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -28,6 +28,8 @@ import org.opengis.metadata.extent.Geogr
 import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.crs.VerticalCRS;
+import org.opengis.referencing.datum.VerticalDatum;
+import org.opengis.referencing.datum.VerticalDatumType;
 import org.apache.sis.measure.Longitude;
 import org.apache.sis.measure.MeasurementRange;
 import org.apache.sis.measure.Range;
@@ -54,7 +56,7 @@ import static org.apache.sis.internal.me
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.6
  * @module
  *
  * @see org.apache.sis.geometry.Envelopes
@@ -132,32 +134,60 @@ public final class Extents extends Stati
     }
 
     /**
-     * Returns the union of all vertical ranges found in the given extent, or {@code null} if none.
-     * Depths have negative height values: if the {@linkplain CoordinateSystemAxis#getDirection() axis direction}
+     * Returns the union of chosen vertical ranges found in the given extent, or {@code null} if none.
+     * This method gives preference to heights above the Mean Sea Level when possible.
+     * Depths have negative height values: if the
+     * {@linkplain org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis#getDirection() axis direction}
      * is toward down, then this method reverses the sign of minimum and maximum values.
      *
      * <div class="section">Multi-occurrences</div>
      * If the given {@code Extent} object contains more than one vertical extent, then this method
-     * performs the following choices:
+     * performs a choice based on the vertical datum and the unit of measurement:
      *
      * <ul>
-     *   <li>If no range specify a unit of measurement, return the first range and ignore all others.</li>
-     *   <li>Otherwise take the first range having a unit of measurement. Then:<ul>
-     *     <li>All other ranges having an incompatible unit of measurement will be ignored.</li>
-     *     <li>All other ranges having a compatible unit of measurement will be converted to
-     *         the unit of the first retained range, and their union will be computed.</li>
-     *   </ul></li>
+     *   <li><p><b>Choice based on vertical datum</b><br>
+     *   Only the extents associated (indirectly, through their CRS) to the same non-null {@link VerticalDatumType}
+     *   will be taken in account. If all datum types are null, then this method conservatively uses only the first
+     *   vertical extent. Otherwise the datum type used for filtering the vertical extents is:</p>
+     *
+     *   <ul>
+     *     <li>{@link VerticalDatumType#GEOIDAL} or {@link VerticalDatumType#DEPTH DEPTH} if at least one extent
+     *         uses those datum types. For this method, {@code DEPTH} is considered as equivalent to {@code GEOIDAL}
+     *         except for the axis direction.</li>
+     *     <li>Otherwise, the first non-null datum type found in iteration order.</li>
+     *   </ul>
+     *
+     *   <div class="note"><b>Rational:</b> like {@linkplain #getGeographicBoundingBox(Extent) geographic bounding box},
+     *   the vertical range is an approximative information; the range returned by this method does not carry any
+     *   information about the vertical CRS and this method does not attempt to perform coordinate transformation.
+     *   But this method is more useful if the returned ranges are close to a frequently used surface, like the
+     *   Mean Sea Level. The same simplification is applied in the
+     *   <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#31">{@code VerticalExtent} element of
+     *   Well Known Text (WKT) format</a>, which specifies that <cite>“Vertical extent is an approximate description
+     *   of location; heights are relative to an unspecified mean sea level.”</cite></div></li>
+     *
+     *   <li><p><b>Choice based on units of measurement</b><br>
+     *   If, after the choice based on the vertical datum described above, there is still more than one vertical
+     *   extent to consider, then the next criterion checks for the units of measurement.</p>
+     *   <ul>
+     *     <li>If no range specify a unit of measurement, return the first range and ignore all others.</li>
+     *     <li>Otherwise take the first range having a unit of measurement. Then:<ul>
+     *       <li>All other ranges having an incompatible unit of measurement will be ignored.</li>
+     *       <li>All other ranges having a compatible unit of measurement will be converted to
+     *           the unit of the first retained range, and their union will be computed.</li>
+     *     </ul></li>
+     *   </ul>
+     *
+     *   <div class="note"><b>Example:</b>
+     *   Heights or depths are often measured using some pressure units, for example hectopascals (hPa).
+     *   An {@code Extent} could contain two vertical elements: one with the height measurements in hPa,
+     *   and the other element with heights transformed to metres using an empirical formula.
+     *   In such case this method will select the first vertical element on the assumption that it is
+     *   the "main" one that the metadata producer intended to show. Next, this method will search for
+     *   other vertical elements using pressure unit. In our example there is none, but if such elements
+     *   were found, this method would compute their union.</div></li>
      * </ul>
      *
-     * <div class="note"><b>Example:</b>
-     * Heights or depths are often measured using some pressure units, for example hectopascals (hPa).
-     * An {@code Extent} could contain two vertical elements: one with the height measurements in hPa,
-     * and the other element with heights transformed to metres using an empirical formula.
-     * In such case this method will select the first vertical element on the assumption that it is
-     * the "main" one that the metadata producer intended to show. Next, this method will search for
-     * other vertical elements using pressure unit. In our example there is none, but if such elements
-     * were found, this method would compute their union.</div>
-     *
      * @param  extent The extent to convert to a vertical measurement range, or {@code null}.
      * @return A vertical measurement range created from the given extent, or {@code null} if none.
      *
@@ -165,13 +195,22 @@ public final class Extents extends Stati
      */
     public static MeasurementRange<Double> getVerticalRange(final Extent extent) {
         MeasurementRange<Double> range = null;
+        VerticalDatumType selectedType = null;
         if (extent != null) {
             for (final VerticalExtent element : extent.getVerticalElements()) {
                 double min = element.getMinimumValue();
                 double max = element.getMaximumValue();
                 final VerticalCRS crs = element.getVerticalCRS();
+                VerticalDatumType type = null;
                 Unit<?> unit = null;
                 if (crs != null) {
+                    final VerticalDatum datum = crs.getDatum();
+                    if (datum != null) {
+                        type = datum.getVerticalDatumType();
+                        if (VerticalDatumType.DEPTH.equals(type)) {
+                            type = VerticalDatumType.GEOIDAL;
+                        }
+                    }
                     final CoordinateSystemAxis axis = crs.getCoordinateSystem().getAxis(0);
                     unit = axis.getUnit();
                     if (AxisDirection.DOWN.equals(axis.getDirection())) {
@@ -182,27 +221,39 @@ public final class Extents extends Stati
                 }
                 if (range != null) {
                     /*
-                     * If the new range does not specify any unit, then we do not know how to convert
-                     * the values before to perform the union operation. Conservatively do nothing.
+                     * If the new range does not specify any datum type or unit, then we do not know how to
+                     * convert the values before to perform the union operation. Conservatively do nothing.
                      */
-                    if (unit == null) {
+                    if (type == null || unit == null) {
                         continue;
                     }
                     /*
-                     * If previous range did not specify any unit, then unconditionally replace it by
-                     * the new range since it provides more information. If both ranges specify units,
-                     * then we will compute the union if we can, or ignore the new range otherwise.
+                     * If the new range is not measured relative to the same kind of surface than the previous range,
+                     * then we do not know how to combine those ranges. Do nothing, unless the new range is a Mean Sea
+                     * Level Height in which case we forget all previous ranges and use the new one instead.
                      */
-                    final Unit<?> previous = range.unit();
-                    if (previous != null) {
-                        if (previous.isCompatible(unit)) {
-                            range = (MeasurementRange<Double>) range.union(
-                                    MeasurementRange.create(min, true, max, true, unit));
+                    if (!type.equals(selectedType)) {
+                        if (!type.equals(VerticalDatumType.GEOIDAL)) {
+                            continue;
+                        }
+                    } else if (selectedType != null) {
+                        /*
+                         * If previous range did not specify any unit, then unconditionally replace it by
+                         * the new range since it provides more information. If both ranges specify units,
+                         * then we will compute the union if we can, or ignore the new range otherwise.
+                         */
+                        final Unit<?> previous = range.unit();
+                        if (previous != null) {
+                            if (previous.isCompatible(unit)) {
+                                range = (MeasurementRange<Double>) range.union(
+                                        MeasurementRange.create(min, true, max, true, unit));
+                            }
+                            continue;
                         }
-                        continue;
                     }
                 }
                 range = MeasurementRange.create(min, true, max, true, unit);
+                selectedType = type;
             }
         }
         return range;

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/ElementTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/ElementTest.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/ElementTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/ElementTest.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -40,7 +40,7 @@ public final strictfp class ElementTest
     /**
      * A dummy parser to be given to the {@link Element} constructor.
      */
-    private final Parser parser = new Parser(Symbols.SQUARE_BRACKETS, null, null, Locale.ENGLISH) {
+    private final AbstractParser parser = new AbstractParser(Symbols.SQUARE_BRACKETS, null, null, null, Locale.ENGLISH) {
         @Override Object parseObject(Element element) throws ParseException {
             throw new UnsupportedOperationException();
         }
@@ -223,7 +223,7 @@ public final strictfp class ElementTest
         Element element = parse("TimeDatum[“Modified Julian”, TimeOrigin[1858-11-17T00:00:00.0Z]]");
         assertEquals("keyword", "TimeDatum", element.keyword);
         assertEquals("name", "Modified Julian", element.pullString("name"));
-        Element inner = element.pullElement("TimeOrigin");
+        Element inner = element.pullElement(AbstractParser.MANDATORY, "TimeOrigin");
         assertEquals("keyword", "TimeOrigin", inner.keyword);
         assertEquals("date", TestUtilities.date("1858-11-17 00:00:00"), inner.pullDate("date"));
         inner.close(null);

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/extent/ExtentsTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/extent/ExtentsTest.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/extent/ExtentsTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/extent/ExtentsTest.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -16,13 +16,20 @@
  */
 package org.apache.sis.metadata.iso.extent;
 
+import java.util.List;
 import java.util.Arrays;
+import java.util.Collections;
 import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+import javax.measure.converter.UnitConverter;
+import javax.measure.converter.ConversionException;
 import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.apache.sis.measure.Units;
 import org.apache.sis.measure.MeasurementRange;
 import org.apache.sis.test.mock.VerticalCRSMock;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
+import org.apache.sis.test.TestUtilities;
 import org.junit.Test;
 
 import static org.apache.sis.internal.metadata.ReferencingServices.NAUTICAL_MILE;
@@ -34,7 +41,7 @@ import static org.junit.Assert.*;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
 @DependsOn(DefaultGeographicBoundingBoxTest.class)
@@ -46,22 +53,41 @@ public final strictfp class ExtentsTest
 
     /**
      * Tests {@link Extents#getVerticalRange(Extent)}.
+     *
+     * @throws ConversionException should never happen in this test.
      */
     @Test
-    public void testGetVerticalRange() {
-        final DefaultExtent extent = new DefaultExtent();
-        extent.setVerticalElements(Arrays.asList(
+    @SuppressWarnings("null")
+    public void testGetVerticalRange() throws ConversionException {
+        final List<DefaultVerticalExtent> extents = Arrays.asList(
                 new DefaultVerticalExtent( -200,  -100, VerticalCRSMock.HEIGHT),
                 new DefaultVerticalExtent(  150,   300, VerticalCRSMock.DEPTH),
                 new DefaultVerticalExtent(  0.1,   0.2, VerticalCRSMock.SIGMA_LEVEL),
-                new DefaultVerticalExtent( -600,  -300, VerticalCRSMock.HEIGHT_ft), // [91.44 182.88] metres
+                new DefaultVerticalExtent( -600,  -300, VerticalCRSMock.HEIGHT_ft), // [91.44 … 182.88] metres
                 new DefaultVerticalExtent(10130, 20260, VerticalCRSMock.BAROMETRIC_HEIGHT)
-        ));
+        );
+        Collections.shuffle(extents, TestUtilities.createRandomNumberGenerator());
+        /*
+         * Since we have shuffled the vertical extents in random order, the range that we will
+         * test may be either in metres or in feet depending on which vertical extent is first.
+         * So we need to check which linear unit is first.
+         */
+        Unit<?> unit = null;
+        for (final DefaultVerticalExtent e : extents) {
+            unit = e.getVerticalCRS().getCoordinateSystem().getAxis(0).getUnit();
+            if (Units.isLinear(unit)) break;
+        }
+        final UnitConverter c = unit.getConverterToAny(SI.METRE);
+        /*
+         * The actual test. Arbitrarily compare the heights in metres, converting them if needed.
+         */
+        final DefaultExtent extent = new DefaultExtent();
+        extent.setVerticalElements(extents);
         final MeasurementRange<Double> range = Extents.getVerticalRange(extent);
         assertNotNull("getVerticalRange", range);
-        assertEquals("unit", SI.METRE,  range.unit());
-        assertEquals("minimum", -300,   range.getMinDouble(), 0.001);
-        assertEquals("maximum", -91.44, range.getMaxDouble(), 0.001);
+        assertSame   ("unit",    unit,    range.unit());
+        assertEquals ("minimum", -300,    c.convert(range.getMinDouble()), 0.001);
+        assertEquals ("maximum", -91.44,  c.convert(range.getMaxDouble()), 0.001);
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/mock/VerticalCRSMock.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/mock/VerticalCRSMock.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/mock/VerticalCRSMock.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/mock/VerticalCRSMock.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -36,7 +36,7 @@ import org.opengis.util.InternationalStr
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
 @SuppressWarnings("serial")
@@ -47,31 +47,36 @@ public final strictfp class VerticalCRSM
      * Height in metres.
      */
     public static final VerticalCRS HEIGHT = new VerticalCRSMock("Height",
-            Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, SI.METRE, true);
+            VerticalDatumType.GEOIDAL, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, SI.METRE, true);
 
     /**
      * Height in feet.
      */
     public static final VerticalCRS HEIGHT_ft = new VerticalCRSMock("Height",
-            Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, NonSI.FOOT, true);
+            VerticalDatumType.GEOIDAL, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, NonSI.FOOT, true);
 
     /**
      * Height estimated from hPa.
      */
     public static final VerticalCRS BAROMETRIC_HEIGHT = new VerticalCRSMock("Barometric height",
-            0, Double.POSITIVE_INFINITY, SI.MetricPrefix.HECTO(SI.PASCAL), true);
+            VerticalDatumType.BAROMETRIC, 0, Double.POSITIVE_INFINITY, SI.MetricPrefix.HECTO(SI.PASCAL), true);
 
     /**
      * Depth in metres.
      */
     public static final VerticalCRS DEPTH = new VerticalCRSMock("Depth",
-            0, Double.POSITIVE_INFINITY, SI.METRE, false);
+            VerticalDatumType.DEPTH, 0, Double.POSITIVE_INFINITY, SI.METRE, false);
 
     /**
      * Depth as a fraction of the sea floor depth at the location of the point for which the depth is evaluated.
      */
     public static final VerticalCRS SIGMA_LEVEL = new VerticalCRSMock("Sigma level",
-            0, 1, Unit.ONE, false);
+            VerticalDatumType.OTHER_SURFACE, 0, 1, Unit.ONE, false);
+
+    /**
+     * The datum type (geoidal, barometric, etc.).
+     */
+    private final VerticalDatumType type;
 
     /**
      * The minimum and maximum values.
@@ -97,10 +102,11 @@ public final strictfp class VerticalCRSM
      * @param minimumValue The minium value.
      * @param maximumValue The maximum value.
      */
-    private VerticalCRSMock(final String name, final double minimumValue, final double maximumValue,
-            final Unit<?> unit, final boolean up)
+    private VerticalCRSMock(final String name, VerticalDatumType type,
+            final double minimumValue, final double maximumValue, final Unit<?> unit, final boolean up)
     {
         super(name);
+        this.type         = type;
         this.minimumValue = minimumValue;
         this.maximumValue = maximumValue;
         this.unit         = unit;
@@ -120,7 +126,7 @@ public final strictfp class VerticalCRSM
     @Override public InternationalString  getAnchorPoint()       {return null;}
     @Override public Date                 getRealizationEpoch()  {return null;}
     @Override public Extent               getDomainOfValidity()  {return null;}
-    @Override public VerticalDatumType    getVerticalDatumType() {return VerticalDatumType.GEOIDAL;}
+    @Override public VerticalDatumType    getVerticalDatumType() {return type;}
     @Override public VerticalDatum        getDatum()             {return this;}
     @Override public VerticalCS           getCoordinateSystem()  {return this;}
     @Override public int                  getDimension()         {return 1;}

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -446,6 +446,18 @@ public final class ServicesForMetadata e
     ///////////////////////////////////////////////////////////////////////////////////////
 
     /**
+     * Returns a coordinate reference system for heights above the mean seal level.
+     *
+     * @return The "Mean Seal Level (MSL) height" coordinate reference system.
+     *
+     * @since 0.6
+     */
+    @Override
+    public VerticalCRS getMSLH() {
+        return CommonCRS.Vertical.MEAN_SEA_LEVEL.crs();
+    }
+
+    /**
      * Returns the Greenwich prime meridian.
      *
      * @return The Greenwich prime meridian.

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -779,7 +779,9 @@ public class AbstractIdentifiedObject ex
      * </ul>
      *
      * <div class="section">Future evolutions</div>
-     * This method implements heuristic rules learned from experience while trying to provide inter-operability
+     * This method implements recommendations from the
+     * <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#139">§B.5.2 of WKT 2 specification</a>,
+     * together with heuristic rules learned from experience while trying to provide inter-operability
      * with different data producers. Those rules may be adjusted in any future SIS version according experience
      * gained while working with more data producers.
      *
@@ -787,6 +789,7 @@ public class AbstractIdentifiedObject ex
      * @return {@code true} if the primary name of at least one alias matches the specified {@code name}.
      *
      * @see IdentifiedObjects#isHeuristicMatchForName(IdentifiedObject, String)
+     * @see org.apache.sis.util.Characters.Filter#LETTERS_AND_DIGITS
      */
     public boolean isHeuristicMatchForName(final String name) {
         return NameToIdentifier.isHeuristicMatchForName(this.name, alias, name);

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -28,6 +28,7 @@ import org.opengis.referencing.cs.Ellips
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
+import org.opengis.referencing.crs.CRSFactory;
 import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.crs.CompoundCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -42,6 +43,7 @@ import org.opengis.metadata.extent.Geogr
 import org.apache.sis.internal.util.DefinitionURI;
 import org.apache.sis.internal.referencing.AxisDirections;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
+import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.referencing.cs.DefaultVerticalCS;
 import org.apache.sis.referencing.cs.DefaultEllipsoidalCS;
 import org.apache.sis.referencing.crs.DefaultGeographicCRS;
@@ -82,7 +84,7 @@ import static java.util.Collections.sing
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.6
  * @module
  */
 public final class CRS extends Static {
@@ -164,7 +166,7 @@ public final class CRS extends Static {
          * that CommonCRS is not expected to succeed if the real EPSG factory threw an exception,
          * so we will log a message at the warning level in such case.
          */
-        CRSAuthorityFactory factory = null; // TODO
+        final CRSAuthorityFactory factory = DefaultFactories.forClass(CRSAuthorityFactory.class);
         if (factory != null) try {
             return factory.createCoordinateReferenceSystem(value);
         } catch (FactoryException failure) {
@@ -177,6 +179,62 @@ public final class CRS extends Static {
     }
 
     /**
+     * Creates a Coordinate Reference System object from a <cite>Well Known Text</cite> (WKT).
+     * The default {@linkplain org.apache.sis.io.wkt Apache SIS parser} understands both
+     * version 1 (a.k.a. OGC 01-009) and version 2 (a.k.a. ISO 19162) of the WKT format.
+     *
+     * <div class="note"><b>Example:</b> below is a slightly simplified WKT 2 string for a Mercator projection.
+     * For making this example smaller, some optional {@code UNIT[…]} and {@code ORDER[…]} elements have been omitted.
+     *
+     * {@preformat wkt
+     *   ProjectedCRS["SIRGAS 2000 / Brazil Mercator",
+     *     BaseGeodCRS["SIRGAS 2000",
+     *       Datum["Sistema de Referencia Geocentrico para las Americas 2000",
+     *         Ellipsoid["GRS 1980", 6378137, 298.257222101]]],
+     *     Conversion["Petrobras Mercator",
+     *       Method["Mercator (variant B)", Id["EPSG",9805]],
+     *       Parameter["Latitude of 1st standard parallel", -2],
+     *       Parameter["Longitude of natural origin", -43],
+     *       Parameter["False easting", 5000000],
+     *       Parameter["False northing", 10000000]],
+     *     CS[cartesian,2],
+     *       Axis["easting (E)", east],
+     *       Axis["northing (N)", north],
+     *       LengthUnit["metre", 1],
+     *     Id["EPSG",5641]]
+     * }
+     * </div>
+     *
+     * <div class="section">Usage and performance considerations</div>
+     * This convenience method delegates to
+     * {@link org.apache.sis.referencing.factory.GeodeticObjectFactory#createFromWKT(String)}
+     * using a default factory instance. This is okay for occasional use, but has the following limitations:
+     *
+     * <ul>
+     *   <li>Performance may be sub-optimal in a multi-thread environment.</li>
+     *   <li>No control on the WKT {@linkplain org.apache.sis.io.wkt.Convention conventions} in use.</li>
+     *   <li>No control on the handling of {@linkplain org.apache.sis.io.wkt.Warnings warnings}.</li>
+     * </ul>
+     *
+     * Applications which need to parse a large amount of WKT strings should consider to use
+     * the {@link org.apache.sis.io.wkt.WKTFormat} class instead than this method.
+     *
+     * @param  text Coordinate system encoded in Well-Known Text format (version 1 or 2).
+     * @return The parsed Coordinate Reference System.
+     * @throws FactoryException if the given WKT can not be parsed.
+     *
+     * @see org.apache.sis.io.wkt
+     * @see org.apache.sis.geometry.Envelopes#fromWKT(CharSequence)
+     * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a>
+     *
+     * @since 0.6
+     */
+    public static CoordinateReferenceSystem fromWKT(final String text) throws FactoryException {
+        ArgumentChecks.ensureNonNull("text", text);
+        return DefaultFactories.forBuildin(CRSFactory.class).createFromWKT(text);
+    }
+
+    /**
      * Returns the valid geographic area for the given coordinate reference system, or {@code null} if unknown.
      * This method explores the {@linkplain CoordinateReferenceSystem#getDomainOfValidity() domain of validity}
      * associated with the given CRS. If more than one geographic bounding box is found, then they will be

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -36,6 +36,7 @@ import org.apache.sis.referencing.Identi
 import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.cs.AbstractCS;
 import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.io.wkt.Formatter;
 
 import static org.apache.sis.util.Utilities.deepEquals;
@@ -520,10 +521,12 @@ public class AbstractCRS extends Abstrac
             formatter.append(toFormattable(cs)); // WKT2 only, since the concept of CoordinateSystem was not explicit in WKT 1.
             formatter.indent(+1);
         }
-        final int dimension = cs.getDimension();
-        for (int i=0; i<dimension; i++) {
-            formatter.newLine();
-            formatter.append(toFormattable(cs.getAxis(i)));
+        if (!isWKT1 || formatter.getConvention() != Convention.WKT1_IGNORE_AXES) {
+            final int dimension = cs.getDimension();
+            for (int i=0; i<dimension; i++) {
+                formatter.newLine();
+                formatter.append(toFormattable(cs.getAxis(i)));
+            }
         }
         if (!isWKT1) { // WKT 2 writes unit after axes, while WKT 1 wrote them before axes.
             formatter.newLine();

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -143,8 +143,8 @@ public enum AxesConvention implements Ax
      * changes are more difficult to handle by coordinate operation factories.
      * </div>
      *
-     * @see CoordinateSystems#normalize(CoordinateSystem)
      * @see org.apache.sis.referencing.CommonCRS#normalizedGeographic()
+     * @see CoordinateSystems#replaceAxes(CoordinateSystem, AxisFilter)
      */
     NORMALIZED {
         @Override

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -43,12 +43,12 @@ import org.apache.sis.referencing.datum.
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.referencing.MergedProperties;
 import org.apache.sis.internal.system.DefaultFactories;
-import org.apache.sis.internal.metadata.WKTParser;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.util.collection.WeakHashSet;
 import org.apache.sis.util.iso.AbstractFactory;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.io.wkt.Parser;
 import org.apache.sis.xml.XML;
 
 
@@ -180,14 +180,14 @@ import org.apache.sis.xml.XML;
  * @version 0.6
  * @module
  */
-public class GeodeticObjectFactory extends AbstractFactory implements CRSFactory, CSFactory, DatumFactory {
+public class GeodeticObjectFactory extends AbstractFactory implements CRSFactory, CSFactory, DatumFactory, Parser {
     /**
      * The constructor for WKT parsers, fetched when first needed. The WKT parser is defined in the
      * same module than this class, so we will hopefully not have security issues.  But we have to
      * use reflection because the parser class is not yet public (because we do not want to commit
      * its API yet).
      */
-    private static volatile Constructor<? extends WKTParser> parserConstructor;
+    private static volatile Constructor<? extends Parser> parserConstructor;
 
     /**
      * The default properties, or an empty map if none. This map shall not change after construction in
@@ -214,7 +214,7 @@ public class GeodeticObjectFactory exten
      * The <cite>Well Known Text</cite> parser for {@code CoordinateReferenceSystem} instances.
      * This parser is not thread-safe, so we need to prevent two threads from using the same instance in same time.
      */
-    private final AtomicReference<WKTParser> parser;
+    private final AtomicReference<Parser> parser;
 
     /**
      * Constructs a factory with no default properties.
@@ -1340,18 +1340,55 @@ public class GeodeticObjectFactory exten
     }
 
     /**
-     * Creates a coordinate reference system object from a string.
+     * Creates a Coordinate Reference System object from a <cite>Well Known Text</cite> (WKT).
+     * This method understands both version 1 (a.k.a. OGC 01-009) and version 2 (a.k.a. ISO 19162)
+     * of the WKT format.
+     *
+     * <div class="note"><b>Example:</b> below is a slightly simplified WKT 2 string for a Mercator projection.
+     * For making this example smaller, some optional {@code UNIT[…]} and {@code ORDER[…]} elements have been omitted.
+     *
+     * {@preformat wkt
+     *   ProjectedCRS["SIRGAS 2000 / Brazil Mercator",
+     *     BaseGeodCRS["SIRGAS 2000",
+     *       Datum["Sistema de Referencia Geocentrico para las Americas 2000",
+     *         Ellipsoid["GRS 1980", 6378137, 298.257222101]]],
+     *     Conversion["Petrobras Mercator",
+     *       Method["Mercator (variant B)", Id["EPSG",9805]],
+     *       Parameter["Latitude of 1st standard parallel", -2],
+     *       Parameter["Longitude of natural origin", -43],
+     *       Parameter["False easting", 5000000],
+     *       Parameter["False northing", 10000000]],
+     *     CS[cartesian,2],
+     *       Axis["easting (E)", east],
+     *       Axis["northing (N)", north],
+     *       LengthUnit["metre", 1],
+     *     Id["EPSG",5641]]
+     * }
+     * </div>
+     *
+     * <div class="section">Usage and performance considerations</div>
+     * The default implementation uses a shared instance of {@link org.apache.sis.io.wkt.WKTFormat}
+     * with the addition of thread-safety. This is okay for occasional use,
+     * but is sub-optimal if this method is extensively used in a multi-thread environment.
+     * Furthermore this method offers no control on the WKT {@linkplain org.apache.sis.io.wkt.Convention conventions}
+     * in use and on the handling of {@linkplain org.apache.sis.io.wkt.Warnings warnings}.
+     * Applications which need to parse a large amount of WKT strings should consider to use
+     * the {@link org.apache.sis.io.wkt.WKTFormat} class instead than this method.
      *
      * @param  text Coordinate system encoded in Well-Known Text format (version 1 or 2).
      * @throws FactoryException if the object creation failed.
+     *
+     * @see org.apache.sis.io.wkt
+     * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a>
+     * @see <a href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html">Legacy WKT 1</a>
      */
     @Override
     public CoordinateReferenceSystem createFromWKT(final String text) throws FactoryException {
-        WKTParser p = parser.getAndSet(null);
+        Parser p = parser.getAndSet(null);
         if (p == null) try {
-            Constructor<? extends WKTParser> c = parserConstructor;
+            Constructor<? extends Parser> c = parserConstructor;
             if (c == null) {
-                c = Class.forName("org.apache.sis.io.wkt.GeodeticObjectParser").asSubclass(WKTParser.class)
+                c = Class.forName("org.apache.sis.io.wkt.GeodeticObjectParser").asSubclass(Parser.class)
                          .getConstructor(Map.class, ObjectFactory.class, MathTransformFactory.class);
                 c.setAccessible(true);
                 parserConstructor = c;

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -46,9 +46,9 @@ import org.opengis.referencing.operation
 import org.opengis.util.FactoryException;
 import org.opengis.util.NoSuchIdentifierException;
 
+import org.apache.sis.io.wkt.Parser;
 import org.apache.sis.internal.util.LazySet;
 import org.apache.sis.internal.util.Constants;
-import org.apache.sis.internal.metadata.WKTParser;
 import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
@@ -155,7 +155,7 @@ import org.apache.sis.internal.jdk8.JDK8
  * @see MathTransformProvider
  * @see AbstractMathTransform
  */
-public class DefaultMathTransformFactory extends AbstractFactory implements MathTransformFactory {
+public class DefaultMathTransformFactory extends AbstractFactory implements MathTransformFactory, Parser {
     /*
      * NOTE FOR JAVADOC WRITER:
      * The "method" word is ambiguous here, because it can be "Java method" or "coordinate operation method".
@@ -177,7 +177,7 @@ public class DefaultMathTransformFactory
      * use reflection because the parser class is not yet public (because we do not want to commit
      * its API yet).
      */
-    private static volatile Constructor<? extends WKTParser> parserConstructor;
+    private static volatile Constructor<? extends Parser> parserConstructor;
 
     /**
      * All methods specified at construction time or found on the classpath.
@@ -221,7 +221,7 @@ public class DefaultMathTransformFactory
      * This parser is not thread-safe, so we need to prevent two threads from using
      * the same instance in same time.
      */
-    private final AtomicReference<WKTParser> parser;
+    private final AtomicReference<Parser> parser;
 
     /**
      * Creates a new factory which will discover operation methods with a {@link ServiceLoader}.
@@ -817,11 +817,11 @@ public class DefaultMathTransformFactory
     @Override
     public MathTransform createFromWKT(final String text) throws FactoryException {
         lastMethod.remove();
-        WKTParser p = parser.getAndSet(null);
+        Parser p = parser.getAndSet(null);
         if (p == null) try {
-            Constructor<? extends WKTParser> c = parserConstructor;
+            Constructor<? extends Parser> c = parserConstructor;
             if (c == null) {
-                c = Class.forName("org.apache.sis.io.wkt.MathTransformParser").asSubclass(WKTParser.class)
+                c = Class.forName("org.apache.sis.io.wkt.MathTransformParser").asSubclass(Parser.class)
                          .getConstructor(MathTransformFactory.class);
                 c.setAccessible(true);
                 parserConstructor = c;

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -18,6 +18,7 @@ package org.apache.sis.io.wkt;
 
 import java.util.Date;
 import java.util.Iterator;
+import java.util.Locale;
 import java.text.ParsePosition;
 import java.text.ParseException;
 import javax.measure.unit.SI;
@@ -68,6 +69,9 @@ public final strictfp class GeodeticObje
     /**
      * Parses the given text.
      *
+     * @param  type The expected object type.
+     * @param  text The WKT string to parse.
+     * @return The parsed object.
      * @throws ParseException if an error occurred during the parsing.
      */
     private <T> T parse(final Class<T> type, final String text) throws ParseException {
@@ -78,6 +82,8 @@ public final strictfp class GeodeticObje
         final Object obj = parser.parseObject(text, position);
         assertEquals("errorIndex", -1, position.getErrorIndex());
         assertEquals("index", text.length(), position.getIndex());
+        assertNull("warnings", parser.getAndClearWarnings(obj));
+        assertTrue("ignoredElements", parser.ignoredElements.isEmpty());
         assertInstanceOf("GeodeticObjectParser.parseObject", type, obj);
         return type.cast(obj);
     }
@@ -85,9 +91,9 @@ public final strictfp class GeodeticObje
     /**
      * Uses a new parser for the given convention.
      */
-    private void setConvention(final Convention convention, final boolean isAxisIgnored) {
+    private void setConvention(final Convention convention) {
         final GeodeticObjectParser p = parser;
-        parser = new GeodeticObjectParser(p.symbols, null, null, convention, isAxisIgnored, p.errorLocale, null);
+        parser = new GeodeticObjectParser(p.symbols, null, null, null, convention, p.errorLocale, null);
     }
 
     /**
@@ -343,7 +349,7 @@ public final strictfp class GeodeticObje
          * So we allow this interpretation in Convention.WKT1_COMMON_UNITS for compatibility reasons.
          */
         wkt = wkt.replace("2.5969213", "2.33722917");   // Convert unit in prime meridian.
-        setConvention(Convention.WKT1_COMMON_UNITS, true);
+        setConvention(Convention.WKT1_IGNORE_AXES);
         crs = parse(GeographicCRS.class, wkt);
         assertNameAndIdentifierEqual("NTF (Paris)", 0, crs);
         pm = verifyNTF(crs.getDatum(), false);
@@ -397,7 +403,7 @@ public final strictfp class GeodeticObje
         wkt = wkt.replace("52.0",      "46.8");             // Convert unit in “latitude_of_origin” parameter.
         wkt = wkt.replace("600.0",     "600000");           // Convert unit in “false_easting” parameter.
         wkt = wkt.replace("2200.0",    "2200000");          // Convert unit in “false_northing” parameter.
-        setConvention(Convention.WKT1_COMMON_UNITS, true);
+        setConvention(Convention.WKT1_IGNORE_AXES);
         crs = parse(ProjectedCRS.class, wkt);
         assertNameAndIdentifierEqual("NTF (Paris) / Lambert zone II", 0, crs);
         verifyProjectedCS(crs.getCoordinateSystem(), SI.KILOMETRE);
@@ -620,4 +626,61 @@ public final strictfp class GeodeticObje
         assertEquals("false_easting",      600000.0, param.parameter("false_easting"     ).doubleValue(SI   .METRE),        STRICT);
         assertEquals("false_northing",     200000.0, param.parameter("false_northing"    ).doubleValue(SI   .METRE),        STRICT);
     }
+
+    /**
+     * Tests the production of a warning messages when the WKT contains unknown elements.
+     *
+     * @throws ParseException if the parsing failed.
+     */
+    @Test
+    @DependsOnMethod("testWithImplicitAxes")
+    public void testWarnings() throws ParseException {
+        parser = new GeodeticObjectParser();
+        final ParsePosition position = new ParsePosition(0);
+        final GeographicCRS crs = (GeographicCRS) parser.parseObject(
+               "  GEOGCS[“WGS 84”,\n" +
+               "    DATUM[“World Geodetic System 1984”,\n" +
+               "      SPHEROID[“WGS84”, 6378137.0, 298.257223563, Ext1[“foo”], Ext2[“bla”]]],\n" +
+               "      PRIMEM[“Greenwich”, 0.0, Intruder[“unknown”]],\n" +
+               "    UNIT[“degree”, 0.017453292519943295], Intruder[“foo”]]", position);
+
+        verifyGeographicCRS(0, crs);
+        assertEquals("errorIndex", -1, position.getErrorIndex());
+        final Warnings warnings = parser.getAndClearWarnings(crs);
+        assertNotNull("warnings", warnings);
+
+        assertTrue("warnings.getExceptions()",
+                warnings.getExceptions().isEmpty());
+
+        assertEquals("warnings.getRootElement()", "WGS 84",
+                warnings.getRootElement());
+
+        assertArrayEquals("warnings.getUnknownElements()",
+                new String[] {"Intruder", "Ext1", "Ext2"},
+                warnings.getUnknownElements().toArray());
+
+        assertArrayEquals("warnings.getUnknownElementLocations(…)",
+                new String[] {"PRIMEM", "GEOGCS"},
+                warnings.getUnknownElementLocations("Intruder").toArray());
+
+        assertArrayEquals("warnings.getUnknownElementLocations(…)",
+                new String[] {"SPHEROID"},
+                warnings.getUnknownElementLocations("Ext1").toArray());
+
+        assertArrayEquals("warnings.getUnknownElementLocations(…)",
+                new String[] {"SPHEROID"},
+                warnings.getUnknownElementLocations("Ext2").toArray());
+
+        assertMultilinesEquals("Parsing of “WGS 84” done, but some elements were ignored.\n" +
+                               " • The text contains unknown elements:\n" +
+                               "    ‣ “Intruder” in PRIMEM, GEOGCS.\n" +
+                               "    ‣ “Ext1” in SPHEROID.\n" +
+                               "    ‣ “Ext2” in SPHEROID.\n", warnings.toString(Locale.US));
+
+        assertMultilinesEquals("La lecture de « WGS 84 » a été faite, mais en ignorant certains éléments.\n" +
+                               " • Le texte contient des éléments inconnus :\n" +
+                               "    ‣ « Intruder » dans PRIMEM, GEOGCS.\n" +
+                               "    ‣ « Ext1 » dans SPHEROID.\n" +
+                               "    ‣ « Ext2 » dans SPHEROID.\n", warnings.toString(Locale.FRANCE));
+    }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractReferenceSystemTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractReferenceSystemTest.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractReferenceSystemTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractReferenceSystemTest.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -123,7 +123,7 @@ public final strictfp class AbstractRefe
                 "  BBox[51.43, 2.54, 55.77, 6.40],\n" +
                 "  VerticalExtent[-1000, -10, LengthUnit[“metre”, 1]],\n" +
                 "  Id[“EPSG”, 4326, “8.2”, URI[“urn:ogc:def:referenceSystem:EPSG:8.2:4326”]],\n" +
-                "  Remarks[“注です。”]]",
+                "  Remark[“注です。”]]",
                 object);
 
         assertWktEquals(Convention.WKT2_SIMPLIFIED,
@@ -133,7 +133,7 @@ public final strictfp class AbstractRefe
                 "  BBox[51.43, 2.54, 55.77, 6.40],\n" +
                 "  VerticalExtent[-1000, -10],\n" +
                 "  Id[“EPSG”, 4326, “8.2”, URI[“urn:ogc:def:referenceSystem:EPSG:8.2:4326”]],\n" +
-                "  Remarks[“注です。”]]",
+                "  Remark[“注です。”]]",
                 object);
 
         assertWktEquals(Convention.INTERNAL,
@@ -143,7 +143,7 @@ public final strictfp class AbstractRefe
                 "  BBox[51.43, 2.54, 55.77, 6.40],\n" +
                 "  VerticalExtent[-1000, -10],\n" +
                 "  Id[“EPSG”, 4326, “8.2”],\n" +
-                "  Remarks[“注です。”]]",
+                "  Remark[“注です。”]]",
                 object);
     }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -158,7 +158,7 @@ public final strictfp class DefaultCompo
                 "    AXIS[“Gravity-related height”, UP]],\n" +
                 "  TIMECRS[“Time”,\n" +
                 "    TIMEDATUM[“Modified Julian”, TIMEORIGIN[1858-11-17T00:00:00.0Z]],\n" +
-                "    UNIT[“day”, 86400],\n" +
+                "    TIMEUNIT[“day”, 86400],\n" +
                 "    AXIS[“Time”, FUTURE]]]",
                 HardCodedCRS.GEOID_4D);
     }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultTemporalCRSTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultTemporalCRSTest.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultTemporalCRSTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultTemporalCRSTest.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -41,7 +41,7 @@ public final strictfp class DefaultTempo
         assertWktEquals(Convention.WKT1,
                 "TIMECRS[“Time”,\n" +
                 "  TIMEDATUM[“Modified Julian”, TIMEORIGIN[1858-11-17T00:00:00.0Z]],\n" +
-                "  UNIT[“day”, 86400],\n" +
+                "  TIMEUNIT[“day”, 86400],\n" +
                 "  AXIS[“Time”, FUTURE]]",
                 HardCodedCRS.TIME);
     }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -274,13 +274,13 @@ public final strictfp class DefaultGeode
         assertWktEquals(Convention.INTERNAL,
                 "Datum[“World Geodetic System 1984”,\n" +
                 "  Ellipsoid[“WGS 84”, 6378137.0, 298.257223563, Id[“EPSG”, 7030],\n" +
-                "    Remarks[“Defining parameters cited in EPSG database.”]],\n" +
+                "    Remark[“Defining parameters cited in EPSG database.”]],\n" +
                 "  Anchor[“Station coordinates changed by a few centimetres in 1994, 1997, 2002 and 2012.”],\n" +
                 "  Scope[“Satellite navigation.”],\n" +
                 "  Area[“World.”],\n" +
                 "  BBox[-90.00, -180.00, 90.00, 180.00],\n" +
                 "  Id[“EPSG”, 6326],\n" +
-                "  Remarks[“No distinction between the original and subsequent WGS 84 frames.”]]",
+                "  Remark[“No distinction between the original and subsequent WGS 84 frames.”]]",
                 datum);
     }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultPrimeMeridianTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultPrimeMeridianTest.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultPrimeMeridianTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultPrimeMeridianTest.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -153,7 +153,7 @@ public final strictfp class DefaultPrime
                 "PrimeMeridian[“Paris”, 2.5969213, AngleUnit[“grade”, 0.015707963267948967], Id[“EPSG”, 8903, URI[“urn:ogc:def:meridian:EPSG::8903”]]]", pm);
         assertWktEquals(Convention.INTERNAL,
                 "PrimeMeridian[“Paris”, 2.5969213, Unit[“grade”, 0.015707963267948967], Id[“EPSG”, 8903],\n" +
-                "  Remarks[“Equivalent to 2°20′14.025″.”]]", pm);
+                "  Remark[“Equivalent to 2°20′14.025″.”]]", pm);
         assertXmlEquals(
                 "<gml:PrimeMeridian xmlns:gml=\"" + Namespaces.GML + "\">\n" +
                 "  <gml:identifier codeSpace=\"IOGP\">urn:ogc:def:meridian:EPSG::8903</gml:identifier>\n" +

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java?rev=1686268&r1=1686267&r2=1686268&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] Thu Jun 18 16:49:25 2015
@@ -166,12 +166,12 @@ public final class Units extends Static
      *
      * @see #isAngular(Unit)
      */
-    @SuppressWarnings({"unchecked","rawtypes"})
+    @SuppressWarnings("unchecked")
     public static Unit<Angle> ensureAngular(final Unit<?> unit) throws IllegalArgumentException {
         if (unit != null && !isAngular(unit)) {
             throw new IllegalArgumentException(Errors.format(Errors.Keys.NonAngularUnit_1, unit));
         }
-        return (Unit) unit;
+        return (Unit<Angle>) unit;
     }
 
     /**
@@ -184,12 +184,12 @@ public final class Units extends Static
      *
      * @see #isLinear(Unit)
      */
-    @SuppressWarnings({"unchecked","rawtypes"})
+    @SuppressWarnings("unchecked")
     public static Unit<Length> ensureLinear(final Unit<?> unit) throws IllegalArgumentException {
         if (unit != null && !isLinear(unit)) {
             throw new IllegalArgumentException(Errors.format(Errors.Keys.NonLinearUnit_1, unit));
         }
-        return (Unit) unit;
+        return (Unit<Length>) unit;
     }
 
     /**
@@ -202,12 +202,12 @@ public final class Units extends Static
      *
      * @see #isTemporal(Unit)
      */
-    @SuppressWarnings({"unchecked","rawtypes"})
+    @SuppressWarnings("unchecked")
     public static Unit<Duration> ensureTemporal(final Unit<?> unit) throws IllegalArgumentException {
         if (unit != null && !isTemporal(unit)) {
             throw new IllegalArgumentException(Errors.format(Errors.Keys.NonTemporalUnit_1, unit));
         }
-        return (Unit) unit;
+        return (Unit<Duration>) unit;
     }
 
     /**
@@ -220,12 +220,12 @@ public final class Units extends Static
      *
      * @see #isScale(Unit)
      */
-    @SuppressWarnings({"unchecked","rawtypes"})
+    @SuppressWarnings("unchecked")
     public static Unit<Dimensionless> ensureScale(final Unit<?> unit) throws IllegalArgumentException {
         if (unit != null && !isScale(unit)) {
             throw new IllegalArgumentException(Errors.format(Errors.Keys.NonScaleUnit_1, unit));
         }
-        return (Unit) unit;
+        return (Unit<Dimensionless>) unit;
     }
 
     /**
@@ -248,14 +248,14 @@ public final class Units extends Static
      * @return The unit multiplied by the given factor.
      */
     @Workaround(library="JSR-275", version="0.9.3")
-    @SuppressWarnings({"unchecked","rawtypes"})
+    @SuppressWarnings("unchecked")
     public static <A extends Quantity> Unit<A> multiply(Unit<A> unit, final double factor) {
         if (SI.RADIAN.equals(unit)) {
             if (abs(factor - (PI / 180)) <= (EPS * PI/180)) {
-                return (Unit) NonSI.DEGREE_ANGLE;
+                return (Unit<A>) NonSI.DEGREE_ANGLE;
             }
             if (abs(factor - (PI / 200)) <= (EPS * PI/200)) {
-                return (Unit) NonSI.GRADE;
+                return (Unit<A>) NonSI.GRADE;
             }
         }
         if (abs(factor - 1) > EPS) {



Mime
View raw message