sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1677853 [2/4] - in /sis/branches/Android: ./ core/sis-feature/src/main/java/org/apache/sis/feature/ core/sis-feature/src/test/java/org/apache/sis/feature/ core/sis-feature/src/test/java/org/apache/sis/test/suite/ core/sis-metadata/src/main...
Date Tue, 05 May 2015 16:17:28 GMT
Modified: sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gts/TM_PeriodDuration.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gts/TM_PeriodDuration.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gts/TM_PeriodDuration.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gts/TM_PeriodDuration.java [UTF-8] Tue May  5 16:17:26 2015
@@ -179,6 +179,8 @@ public final class TM_PeriodDuration ext
      * @param e The exception.
      */
     private static void warningOccured(final String methodName, final Exception e) {
-        Context.warningOccured(Context.current(), TM_PeriodDuration.class, methodName, e, true);
+        if (TemporalUtilities.REPORT_MISSING_MODULE || !e.getMessage().contains("sis-temporal")) {
+            Context.warningOccured(Context.current(), TM_PeriodDuration.class, methodName, e, true);
+        }
     }
 }

Modified: sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java [UTF-8] Tue May  5 16:17:26 2015
@@ -55,13 +55,7 @@ import org.apache.sis.metadata.iso.citat
 public enum Convention {
     /**
      * The ISO 19162 format, also known as “WKT 2”.
-     * This convention follows the ISO recommendations with the following exceptions:
-     *
-     * <ul>
-     *   <li>{@code Axis} element omits the {@code Order} sub-element.</li>
-     * </ul>
-     *
-     * Since the {@code Order} element is optional, the WKT is still valid.
+     * This convention follows the ISO recommendations.
      *
      * <p>Unless otherwise specified by {@link WKTFormat#setNameAuthority(Citation)}, projections
      * and parameters formatted with this convention will use the {@linkplain Citations#EPSG EPSG}
@@ -77,6 +71,8 @@ public enum Convention {
      * to the {@link #WKT2} convention except for the following aspects:
      *
      * <ul>
+     *   <li>{@code PrimeMeridian} element omitted if the meridian is Greenwich.</li>
+     *   <li>{@code Axis} element omits the {@code Order} sub-element.</li>
      *   <li>{@code VerticalExtent} element omits the {@code LengthUnit} sub-element
      *       if the unit is {@link javax.measure.unit.SI#METRE}.</li>
      *   <li>{@code Ellipsoid} element omits the {@code LengthUnit} sub-element

Modified: sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java [UTF-8] Tue May  5 16:17:26 2015
@@ -169,10 +169,11 @@ public class Formatter implements Locali
     private Citation authority;
 
     /**
-     * {@code true} for preserving non-ASCII characters. The default value is {@code false},
-     * which causes replacements like "é" → "e" in all elements except {@code REMARKS["…"]}.
+     * {@link CharEncoding#UNICODE} for preserving non-ASCII characters. The default value is
+     * {@link CharEncoding#DEFAULT}, which causes replacements like "é" → "e" in all elements
+     * except {@code REMARKS["…"]}. May also be a user-supplied encoding.
      */
-    boolean isNonAsciiAllowed;
+    CharEncoding encoding;
 
     /**
      * The enclosing WKT element being formatted.
@@ -384,7 +385,7 @@ public class Formatter implements Locali
         this.colors       = colors;
         this.toUpperCase  = toUpperCase;
         this.indentation  = indentation;
-        isNonAsciiAllowed = (convention == Convention.INTERNAL);
+        this.encoding     = (convention == Convention.INTERNAL) ? CharEncoding.UNICODE : CharEncoding.DEFAULT;
     }
 
     /**
@@ -400,6 +401,28 @@ public class Formatter implements Locali
     }
 
     /**
+     * Returns a mapper between Java character sequences and the characters to write in WKT.
+     * The intend is to specify how to write characters that are not allowed in WKT strings
+     * according ISO 19162 specification. Return values can be:
+     *
+     * <ul>
+     *   <li>{@link CharEncoding#DEFAULT} for performing replacements like "é" → "e"
+     *       in all WKT elements except {@code REMARKS["…"]}.</li>
+     *   <li>{@link CharEncoding#UNICODE} for preserving non-ASCII characters.</li>
+     *   <li>Any other user-supplied mapping.</li>
+     * </ul>
+     *
+     * @return The mapper between Java character sequences and the characters to write in WKT.
+     *
+     * @see WKTFormat#setCharEncoding(CharEncoding)
+     *
+     * @since 0.6
+     */
+    public final CharEncoding getCharEncoding() {
+        return encoding;
+    }
+
+    /**
      * Returns the preferred authority for choosing the projection and parameter names.
      *
      * <p>The preferred authority can be set by the {@link WKTFormat#setNameAuthority(Citation)} method.
@@ -928,10 +951,10 @@ public class Formatter implements Locali
     private void quote(final String text, final ElementKind type) {
         setColor(type);
         final int base = buffer.appendCodePoint(symbols.getOpeningQuote(0)).length();
-        if (isNonAsciiAllowed || (type == ElementKind.REMARKS)) {
+        if (type == ElementKind.REMARKS) {
             buffer.append(text);
         } else {
-            buffer.append(CharSequences.toASCII(text));
+            buffer.append(encoding.filter(text));
         }
         closeQuote(base);
         resetColor();
@@ -1105,7 +1128,9 @@ public class Formatter implements Locali
             openElement(false, keyword);
             setColor(ElementKind.UNIT);
             final int fromIndex = buffer.appendCodePoint(symbols.getOpeningQuote(0)).length();
-            if (NonSI.DEGREE_ANGLE.equals(unit)) {
+            if (Unit.ONE.equals(unit)) {
+                buffer.append("unity");
+            } else if (NonSI.DEGREE_ANGLE.equals(unit)) {
                 buffer.append("degree");
             } else if (SI.METRE.equals(unit)) {
                 buffer.append(convention.usesCommonUnits() ? "meter" : "metre");
@@ -1351,22 +1376,21 @@ public class Formatter implements Locali
      * Applications can test {@link #isInvalidWKT()} later for checking WKT validity.
      *
      * <p>If any {@code setInvalidWKT(…)} method is invoked more than once during formatting,
-     * then only information about the first failure will be retained.</p>
+     * then only information about the last failure will be retained. The reason is that the
+     * last failure is typically the enclosing element.</p>
      *
      * @param unformattable The object that can not be formatted,
      * @param cause The cause for the failure to format, or {@code null} if the cause is not an exception.
      */
     public void setInvalidWKT(final IdentifiedObject unformattable, final Exception cause) {
         ArgumentChecks.ensureNonNull("unformattable", unformattable);
-        if (invalidElement == null) {
-            String name;
-            final Identifier id = unformattable.getName();
-            if (id == null || (name = id.getCode()) == null) {
-                name = getName(unformattable.getClass());
-            }
-            invalidElement = name;
-            errorCause     = cause;
+        String name;
+        final Identifier id = unformattable.getName();
+        if (id == null || (name = id.getCode()) == null) {
+            name = getName(unformattable.getClass());
         }
+        invalidElement = name;
+        errorCause     = cause;
         highlightError = true;
     }
 

Modified: sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/WKTFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/WKTFormat.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/WKTFormat.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/WKTFormat.java [UTF-8] Tue May  5 16:17:26 2015
@@ -41,10 +41,11 @@ import org.apache.sis.util.resources.Err
  * {@code WKTFormat} objects allow the following configuration:
  *
  * <ul>
- *   <li>The {@linkplain Symbols symbols} to use (curly braces or brackets, <i>etc</i>).</li>
  *   <li>The preferred authority of {@linkplain IdentifiedObject#getName() object name} to
  *       format (see {@link Formatter#getNameAuthority()} for more information).</li>
- *   <li>Whatever ANSI X3.64 colors are allowed or not (default is not).</li>
+ *   <li>The {@linkplain Symbols symbols} to use (curly braces or brackets, <i>etc</i>).</li>
+ *   <li>The {@linkplain CharEncoding character encoding} (i.e. replacements to use for Unicode characters).</li>
+ *   <li>Whether ANSI X3.64 colors are allowed or not (default is not).</li>
  *   <li>The indentation.</li>
  * </ul>
  *
@@ -78,7 +79,7 @@ import org.apache.sis.util.resources.Err
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Rémi Eve (IRD)
  * @since   0.4
- * @version 0.5
+ * @version 0.6
  * @module
  */
 public class WKTFormat extends CompoundFormat<Object> {
@@ -150,10 +151,13 @@ public class WKTFormat extends CompoundF
     private KeywordCase keywordCase;
 
     /**
-     * {@code true} for preserving non-ASCII characters. The default value is {@code false},
-     * which causes replacements like "é" → "e" in all elements except {@code REMARKS["…"]}.
+     * {@link CharEncoding#UNICODE} for preserving non-ASCII characters. The default value is
+     * {@link CharEncoding#DEFAULT}, which causes replacements like "é" → "e" in all elements
+     * except {@code REMARKS["…"]}. May also be a user-supplied encoding.
+     *
+     * <p>A {@code null} value means to infer this property from the {@linkplain #convention}.</p>
      */
-    private boolean isNonAsciiAllowed;
+    private CharEncoding encoding;
 
     /**
      * The amount of spaces to use in indentation, or {@value #SINGLE_LINE} if indentation is disabled.
@@ -207,6 +211,45 @@ public class WKTFormat extends CompoundF
     }
 
     /**
+     * Returns a mapper between Java character sequences and the characters to write in WKT.
+     * The intend is to specify how to write characters that are not allowed in WKT strings
+     * according ISO 19162 specification. Return values can be:
+     *
+     * <ul>
+     *   <li>{@link CharEncoding#DEFAULT} for performing replacements like "é" → "e"
+     *       in all WKT elements except {@code REMARKS["…"]}.</li>
+     *   <li>{@link CharEncoding#UNICODE} for preserving non-ASCII characters.</li>
+     *   <li>Any other user-supplied mapping.</li>
+     * </ul>
+     *
+     * @return The mapper between Java character sequences and the characters to write in WKT.
+     *
+     * @since 0.6
+     */
+    public CharEncoding getCharEncoding() {
+        CharEncoding result = encoding;
+        if (result == null) {
+            result = (convention == Convention.INTERNAL) ? CharEncoding.UNICODE : CharEncoding.DEFAULT;
+        }
+        return result;
+    }
+
+    /**
+     * Sets the mapper between Java character sequences and the characters to write in WKT.
+     *
+     * <p>If this method is never invoked, or if this method is invoked with a {@code null} value,
+     * then the default mapper is {@link CharEncoding#DEFAULT} except for WKT formatted according
+     * the {@linkplain Convention#INTERNAL internal convention}.</p>
+     *
+     * @param encoding The new mapper to use, or {@code null} for restoring the default value.
+     *
+     * @since 0.6
+     */
+    public void setCharEncoding(final CharEncoding encoding) {
+        this.encoding = encoding;
+    }
+
+    /**
      * Returns whether non-ASCII characters are preserved. The default value is {@code false},
      * which causes replacements like "é" → "e" in all elements except {@link ElementKind#REMARKS}.
      *
@@ -216,9 +259,12 @@ public class WKTFormat extends CompoundF
      * @return Whether non-ASCII characters are preserved.
      *
      * @since 0.5
+     *
+     * @deprecated Replaced by {@link #getCharEncoding()}.
      */
+    @Deprecated
     public boolean isNonAsciiAllowed() {
-        return isNonAsciiAllowed || (convention == Convention.INTERNAL);
+        return getCharEncoding() == CharEncoding.UNICODE;
     }
 
     /**
@@ -229,9 +275,12 @@ public class WKTFormat extends CompoundF
      * @param allowed Whether non-ASCII characters shall be preserved.
      *
      * @since 0.5
+     *
+     * @deprecated Replaced by {@link #setCharEncoding(CharEncoding)}.
      */
+    @Deprecated
     public void setNonAsciiAllowed(final boolean allowed) {
-        isNonAsciiAllowed = allowed;
+        setCharEncoding(allowed ? CharEncoding.UNICODE : CharEncoding.DEFAULT);
     }
 
     /**
@@ -364,7 +413,9 @@ public class WKTFormat extends CompoundF
                 default: toUpperCase = (convention.majorVersion() == 1); break;
             }
             formatter.configure(convention, authority, colors, toUpperCase, indentation);
-            formatter.isNonAsciiAllowed |= isNonAsciiAllowed;
+            if (encoding != null) {
+                formatter.encoding = encoding;
+            }
         }
     }
 

Modified: sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] Tue May  5 16:17:26 2015
@@ -550,19 +550,30 @@ public class ImmutableIdentifier extends
     @Override
     protected String formatTo(final Formatter formatter) {
         String keyword = null;
+        /*
+         * The code, codeSpace, authority and version local variables in this method usually have the exact same
+         * value than the fields of the same name in this class.  But we get those values by invoking the public
+         * methods in order to give to users a chance to override those properties.  The intend is also to use a
+         * consistent approach for all 'formatTo' implementations, since some other classes have no choice other
+         * than using the public methods.
+         */
+        final String code = getCode();
         if (code != null) {
+            final String   codeSpace = getCodeSpace();
+            final Citation authority = getAuthority();
             final String cs = (codeSpace != null) ? codeSpace :
                     org.apache.sis.internal.util.Citations.getIdentifier(authority, true);
             if (cs != null) {
                 final Convention convention = formatter.getConvention();
                 if (convention.majorVersion() == 1) {
                     keyword = "Authority";
-                    formatter.append(cs, ElementKind.IDENTIFIER);
+                    formatter.append(cs,   ElementKind.IDENTIFIER);
                     formatter.append(code, ElementKind.IDENTIFIER);
                 } else {
                     keyword = "Id";
                     formatter.append(cs, ElementKind.IDENTIFIER);
                     appendCode(formatter, code);
+                    final String version = getVersion();
                     if (version != null) {
                         appendCode(formatter, version);
                     }

Modified: sis/branches/Android/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/FormatterTest.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/FormatterTest.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/FormatterTest.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-metadata/src/test/java/org/apache/sis/io/wkt/FormatterTest.java [UTF-8] Tue May  5 16:17:26 2015
@@ -58,6 +58,9 @@ public final strictfp class FormatterTes
     @Test
     public void testQuote() {
         assertWktEquals(Convention.WKT2,
+                "“A \"quote\" to replace”",             // Expect replacement of non-latin characters.
+                 "A “quote” to replace");
+        assertWktEquals(Convention.INTERNAL,
                 "“A “quote”” to double”",               // Expect doubling quotes.
                  "A “quote” to double");
         assertWktEquals(Convention.WKT2,

Modified: sis/branches/Android/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java [UTF-8] Tue May  5 16:17:26 2015
@@ -93,6 +93,7 @@ import org.junit.BeforeClass;
 
     org.apache.sis.io.wkt.ConventionTest.class,
     org.apache.sis.io.wkt.SymbolsTest.class,
+    org.apache.sis.io.wkt.CharEncodingTest.class,
     org.apache.sis.io.wkt.ColorsTest.class,
     org.apache.sis.io.wkt.FormatterTest.class,
     org.apache.sis.io.wkt.WKTFormatTest.class

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/OperationMethods.java [UTF-8] Tue May  5 16:17:26 2015
@@ -16,21 +16,17 @@
  */
 package org.apache.sis.internal.referencing;
 
-import java.util.Map;
-import org.opengis.metadata.Identifier;
-import org.opengis.metadata.citation.Citation;
-import org.opengis.referencing.ReferenceIdentifier;
-import org.opengis.referencing.operation.Matrix;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.OperationMethod;
-import org.apache.sis.referencing.AbstractIdentifiedObject;
-import org.apache.sis.referencing.operation.transform.MathTransforms;
-import org.apache.sis.referencing.operation.transform.PassThroughTransform;
-import org.apache.sis.internal.util.Citations;
-import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.Characters;
+import java.util.Collection;
+import org.opengis.util.Record;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+import javax.measure.quantity.Length;
+import org.opengis.metadata.quality.Result;
+import org.opengis.metadata.quality.PositionalAccuracy;
+import org.opengis.metadata.quality.QuantitativeResult;
+import org.opengis.referencing.operation.*;
 import org.apache.sis.util.Static;
+import org.apache.sis.measure.Units;
 
 
 /**
@@ -39,173 +35,116 @@ import org.apache.sis.util.Static;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.5
+ * @version 0.6
  * @module
  */
 public final class OperationMethods extends Static {
     /**
-     * Do not allow instantiation of this class.
+     * The key for specifying explicitely the value to be returned by
+     * {@link org.apache.sis.referencing.operation.DefaultSingleOperation#getParameterValues()}.
+     * It is usually not necessary to specify those parameters because they are inferred either from
+     * the {@link MathTransform}, or specified explicitely in a {@code DefiningConversion}. However
+     * there is a few cases, for example the Molodenski transform, where none of the above can apply,
+     * because SIS implements those operations as a concatenation of math transforms, and such
+     * concatenations do not have {@link org.opengis.parameter.ParameterValueGroup}.
      */
-    private OperationMethods() {
-    }
+    public static final String PARAMETERS_KEY = "parameters";
 
     /**
-     * Determines whether a match or mismatch is found between the two given collections of identifiers.
-     * If any of the given collections is {@code null} or empty, this method returns {@code null}.
-     *
-     * <p>According ISO 19162 (<cite>Well known text representation of coordinate reference systems</cite>),
-     * {@linkplain AbstractIdentifiedObject#getIdentifier() identifiers} should have precedence over
-     * {@linkplain AbstractIdentifiedObject#getName() name} for identifying {@code IdentifiedObject}s,
-     * at least in the case of {@linkplain org.apache.sis.referencing.operation.DefaultOperationMethod
-     * operation methods} and {@linkplain org.apache.sis.parameter.AbstractParameterDescriptor parameters}.</p>
-     *
-     * @param  id1 The first collection of identifiers, or {@code null}.
-     * @param  id2 The second collection of identifiers, or {@code null}.
-     * @return {@code TRUE} or {@code FALSE} on match or mismatch respectively, or {@code null} if this method
-     *         can not determine if there is a match or mismatch.
-     */
-    public static Boolean hasCommonIdentifier(final Iterable<? extends Identifier> id1,
-                                              final Iterable<? extends Identifier> id2)
-    {
-        if (id1 != null && id2 != null) {
-            boolean hasFound = false;
-            for (final Identifier identifier : id1) {
-                final Citation authority = identifier.getAuthority();
-                final String   codeSpace = (identifier instanceof ReferenceIdentifier) ? ((ReferenceIdentifier) identifier).getCodeSpace() : null;
-                for (final Identifier other : id2) {
-                    if (authorityMatches(identifier, authority, codeSpace)) {
-                        if (CharSequences.equalsFiltered(identifier.getCode(), other.getCode(), Characters.Filter.UNICODE_IDENTIFIER, true)) {
-                            return Boolean.TRUE;
-                        }
-                        hasFound = true;
-                    }
-                }
-            }
-            if (hasFound) {
-                return Boolean.FALSE;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns {@code true} if the given identifier authority matches the given {@code authority}.
-     * If one of the authority is null, then the comparison fallback on the given {@code codeSpace}.
-     * If the code spaces are also null, then this method conservatively returns {@code false}.
-     *
-     * @param  identifier The identifier to compare.
-     * @param  authority  The desired authority, or {@code null}.
-     * @param  codeSpace  The desired code space or {@code null}, used as a fallback if an authority is null.
-     * @return {@code true} if the authority or code space (as a fallback only) matches.
+     * Do not allow instantiation of this class.
      */
-    private static boolean authorityMatches(final Identifier identifier, final Citation authority, final String codeSpace) {
-        if (authority != null) {
-            final Citation other = identifier.getAuthority();
-            if (other != null) {
-                return Citations.identifierMatches(authority, other);
-            }
-        }
-        if (codeSpace != null) {
-            final String other = (identifier instanceof ReferenceIdentifier) ? ((ReferenceIdentifier) identifier).getCodeSpace() : null;
-            if (other != null) {
-                return CharSequences.equalsFiltered(codeSpace, other, Characters.Filter.UNICODE_IDENTIFIER, true);
-            }
-        }
-        return false;
+    private OperationMethods() {
     }
 
     /**
-     * Checks if an operation method and a math transform have a compatible number of source and target dimensions.
-     * In the particular case of a {@linkplain PassThroughTransform pass through transform} with more dimensions
-     * than what we would expect from the given method, the check will rather be performed against the
-     * {@linkplain PassThroughTransform#getSubTransform() sub transform}.
-     *
-     * <p>The intend is to allow creation of a three-dimensional {@code ProjectedCRS} with a two-dimensional
-     * {@code OperationMethod}, where the third-dimension just pass through. This is not a recommended approach
-     * and we do not document that as a supported feature, but we do not prevent it neither.</p>
-     *
-     * <p>This method tries to locates what seems to be the "core" of the given math transform. The definition
-     * of "core" is imprecise and may be adjusted in future SIS versions. The current algorithm is as below:</p>
+     * Convenience method returning the accuracy in meters for the specified operation.
+     * This method tries each of the following procedures and returns the first successful one:
      *
      * <ul>
-     *   <li>If the given transform can be decomposed in {@linkplain MathTransforms#getSteps(MathTransform) steps},
-     *       then the steps for {@linkplain org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes axis
-     *       swapping and scaling} are ignored.</li>
-     *   <li>If the given transform or its non-ignorable step is a {@link PassThroughTransform}, then its sub-transform
-     *       is taken. Only one non-ignorable step may exist, otherwise we do not try to select any of them.</li>
+     *   <li>If a {@link QuantitativeResult} is found with a linear unit, then this accuracy estimate
+     *       is converted to {@linkplain SI#METRE metres} and returned.</li>
+     *   <li>Otherwise, if the operation is a {@link Conversion}, then returns 0 since a conversion
+     *       is by definition accurate up to rounding errors.</li>
+     *   <li>Otherwise, if the operation is a {@link Transformation}, then checks if the datum shift
+     *       were applied with the help of Bursa-Wolf parameters. This procedure looks for SIS-specific
+     *       {@link PositionalAccuracyConstant#DATUM_SHIFT_APPLIED} and
+     *       {@link PositionalAccuracyConstant#DATUM_SHIFT_OMITTED DATUM_SHIFT_OMITTED} constants.</li>
+     *   <li>Otherwise, if the operation is a {@link ConcatenatedOperation}, returns the sum of the accuracy
+     *       of all components. This is a conservative scenario where we assume that errors cumulate linearly.
+     *       Note that this is not necessarily the "worst case" scenario since the accuracy could be worst
+     *       if the math transforms are highly non-linear.</li>
      * </ul>
      *
-     * @param  method     The operation method to compare to the math transform.
-     * @param  transform  The math transform to compare to the operation method.
-     * @param  properties Properties of the caller object being constructed, used only for formatting error message.
-     * @throws IllegalArgumentException if the number of dimensions are incompatible.
+     * If the above is modified, please update {@code AbstractCoordinateOperation.getLinearAccuracy()} javadoc.
+     *
+     * @param  operation The operation to inspect for accuracy.
+     * @return The accuracy estimate (always in meters), or NaN if unknown.
+     *
+     * @see org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
      */
-    public static void checkDimensions(final OperationMethod method, MathTransform transform,
-            final Map<String,?> properties) throws IllegalArgumentException
-    {
-        int actual = transform.getSourceDimensions();
-        Integer expected = method.getSourceDimensions();
-        if (expected != null && actual > expected) {
-            /*
-             * The given MathTransform use more dimensions than the OperationMethod.
-             * Try to locate one and only one sub-transform, ignoring axis swapping and scaling.
-             */
-            MathTransform subTransform = null;
-            for (final MathTransform step : MathTransforms.getSteps(transform)) {
-                if (!isIgnorable(step)) {
-                    if (subTransform == null && step instanceof PassThroughTransform) {
-                        subTransform = ((PassThroughTransform) step).getSubTransform();
-                    } else {
-                        subTransform = null;
-                        break;
+    public static double getLinearAccuracy(final CoordinateOperation operation) {
+        final Collection<PositionalAccuracy> accuracies = operation.getCoordinateOperationAccuracy();
+        for (final PositionalAccuracy accuracy : accuracies) {
+            for (final Result result : accuracy.getResults()) {
+                if (result instanceof QuantitativeResult) {
+                    final QuantitativeResult quantity = (QuantitativeResult) result;
+                    final Collection<? extends Record> records = quantity.getValues();
+                    if (records != null) {
+                        final Unit<?> unit = quantity.getValueUnit();
+                        if (Units.isLinear(unit)) {
+                            final Unit<Length> unitOfLength = unit.asType(Length.class);
+                            for (final Record record : records) {
+                                for (final Object value : record.getAttributes().values()) {
+                                    if (value instanceof Number) {
+                                        double v = ((Number) value).doubleValue();
+                                        v = unitOfLength.getConverterTo(SI.METRE).convert(v);
+                                        return v;
+                                    }
+                                }
+                            }
+                        }
                     }
                 }
             }
-            if (subTransform != null) {
-                transform = subTransform;
-                actual = transform.getSourceDimensions();
-            }
         }
         /*
-         * Now verify if the MathTransform dimensions are equal to the OperationMethod ones,
-         * ignoring null java.lang.Integer instances.
+         * No quantitative (linear) accuracy were found. If the coordinate operation is actually
+         * a conversion, the accuracy is up to rounding error (i.e. conceptually 0) by definition.
+         */
+        if (operation instanceof Conversion) {
+            return 0;
+        }
+        /*
+         * If the coordinate operation is actually a transformation, checks if Bursa-Wolf parameters
+         * were available for the datum shift. This is SIS-specific. See field javadoc for a rational
+         * about the return values chosen.
          */
-        byte isTarget = 0; // false: wrong dimension is the source one.
-        if (expected == null || actual == expected) {
-            actual = transform.getTargetDimensions();
-            expected = method.getTargetDimensions();
-            if (expected == null || actual == expected) {
-                return;
+        if (operation instanceof Transformation) {
+            if (!accuracies.contains(PositionalAccuracyConstant.DATUM_SHIFT_OMITTED)) {
+                if (accuracies.contains(PositionalAccuracyConstant.DATUM_SHIFT_APPLIED)) {
+                    return PositionalAccuracyConstant.DATUM_SHIFT_ACCURACY;
+                }
             }
-            isTarget = 1; // true: wrong dimension is the target one.
+            return PositionalAccuracyConstant.UNKNOWN_ACCURACY;
         }
-        throw new IllegalArgumentException(Errors.getResources(properties).getString(
-                Errors.Keys.MismatchedTransformDimension_3, isTarget, expected, actual));
-    }
-
-    /**
-     * Returns {@code true} if the specified transform is likely to exists only for axis swapping
-     * and/or unit conversions. The heuristic rule checks if the transform is backed by a square
-     * matrix with exactly one non-null value in each row and each column.
-     */
-    private static boolean isIgnorable(final MathTransform transform) {
-        final Matrix matrix = MathTransforms.getMatrix(transform);
-        if (matrix != null) {
-            final int size = matrix.getNumRow();
-            if (matrix.getNumCol() == size) {
-                for (int j=0; j<size; j++) {
-                    int n1=0, n2=0;
-                    for (int i=0; i<size; i++) {
-                        if (matrix.getElement(j,i) != 0) n1++;
-                        if (matrix.getElement(i,j) != 0) n2++;
-                    }
-                    if (n1 != 1 || n2 != 1) {
-                        return false;
+        /*
+         * If the coordinate operation is a compound of other coordinate operations, returns the sum of their accuracy,
+         * skipping unknown ones. Making the sum is a conservative approach (not exactly the "worst case" scenario,
+         * since it could be worst if the transforms are highly non-linear).
+         */
+        double accuracy = Double.NaN;
+        if (operation instanceof ConcatenatedOperation) {
+            for (final SingleOperation op : ((ConcatenatedOperation) operation).getOperations()) {
+                final double candidate = Math.abs(getLinearAccuracy(op));
+                if (!Double.isNaN(candidate)) {
+                    if (Double.isNaN(accuracy)) {
+                        accuracy = candidate;
+                    } else {
+                        accuracy += candidate;
                     }
                 }
-                return true;
             }
         }
-        return false;
+        return accuracy;
     }
 }

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java [UTF-8] Tue May  5 16:17:26 2015
@@ -34,7 +34,7 @@ import org.apache.sis.util.resources.Mes
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.5
+ * @version 0.6
  * @module
  *
  * @see org.opengis.referencing.operation.Transformation#getCoordinateOperationAccuracy()
@@ -47,6 +47,28 @@ public final class PositionalAccuracyCon
     private static final long serialVersionUID = -2554090935254116470L;
 
     /**
+     * Presumed worst case error when no datum shift information was found.
+     * The highest value found in the EPSG database 6.7 is 999 metres (worst datum shift), so this error
+     * should be yet higher. I have seen 3 kilometres mentioned in some documentation somewhere.
+     *
+     * <p>If this value is modified, please update {@code getLinearAccuracy()} public javadoc accordingly.</p>
+     *
+     * @see org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
+     */
+    public static final double UNKNOWN_ACCURACY = 3000;
+
+    /**
+     * Default accuracy of datum shift, if not explicitly provided in the EPSG database.
+     * The 25 meters value is the next highest value (after 999 metres) found in the EPSG
+     * database version 6.7 for a significant number of transformations.
+     *
+     * <p>If this value is modified, please update {@code getLinearAccuracy()} public javadoc accordingly.</p>
+     *
+     * @see org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
+     */
+    public static final double DATUM_SHIFT_ACCURACY = 25;
+
+    /**
      * Indicates that a {@linkplain org.opengis.referencing.operation.Transformation transformation}
      * requires a datum shift and some method has been applied. Datum shift methods often use
      * {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa Wolf parameters},

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] Tue May  5 16:17:26 2015
@@ -19,6 +19,7 @@ package org.apache.sis.internal.referenc
 import java.util.Collection;
 import java.util.logging.Logger;
 import javax.measure.unit.Unit;
+import javax.measure.unit.NonSI;
 import javax.measure.quantity.Angle;
 import org.opengis.annotation.UML;
 import org.opengis.annotation.Specification;
@@ -36,6 +37,7 @@ import org.apache.sis.referencing.Common
 import org.apache.sis.referencing.datum.DefaultPrimeMeridian;
 import org.apache.sis.referencing.crs.DefaultGeographicCRS;
 import org.apache.sis.referencing.cs.AxesConvention;
+import org.apache.sis.measure.Units;
 
 import static java.util.Collections.singletonMap;
 import static org.apache.sis.internal.util.Numerics.epsilonEqual;
@@ -106,6 +108,32 @@ public final class ReferencingUtilities
     }
 
     /**
+     * Returns the angular unit of the specified coordinate system.
+     * The preference will be given to the longitude axis, if found.
+     *
+     * @param  cs The coordinate system from which to get the angular unit, or {@code null}.
+     * @return The angular unit, of {@link NonSI#DEGREE_ANGLE} if no angular unit was found.
+     *
+     * @since 0.6
+     */
+    public static Unit<Angle> getAngularUnit(final CoordinateSystem cs) {
+        Unit<Angle> unit = NonSI.DEGREE_ANGLE;
+        if (cs != null) {
+            for (int i = cs.getDimension(); --i>=0;) {
+                final CoordinateSystemAxis axis = cs.getAxis(i);
+                final Unit<?> candidate = axis.getUnit();
+                if (Units.isAngular(candidate)) {
+                    unit = candidate.asType(Angle.class);
+                    if (AxisDirection.EAST.equals(AxisDirections.absolute(axis.getDirection()))) {
+                        break; // Found the longitude axis.
+                    }
+                }
+            }
+        }
+        return unit;
+    }
+
+    /**
      * Returns the unit used for all axes in the given coordinate system.
      * If not all axes use the same unit, then this method returns {@code null}.
      *

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ParameterizedAffine.java [UTF-8] Tue May  5 16:17:26 2015
@@ -106,7 +106,8 @@ public final class ParameterizedAffine e
      */
     @Override
     public ParameterDescriptorGroup getParameterDescriptors() {
-        return isDefinitive ? parameters.getDescriptor() : super.getParameterDescriptors();
+        return isDefinitive || Semaphores.query(Semaphores.PROJCS)  // See comment in getParameterValues().
+               ? parameters.getDescriptor() : super.getParameterDescriptors();
     }
 
     /**

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java [UTF-8] Tue May  5 16:17:26 2015
@@ -115,6 +115,8 @@ abstract class AbstractProvider extends
 
     /**
      * Creates a descriptor for a constant value in degrees.
+     *
+     * @see MapProjection#validate(ParameterDescriptor, double)
      */
     static ParameterDescriptor<Double> createConstant(final ParameterBuilder builder, final Double constant) {
         return builder.createBounded(MeasurementRange.create(constant, true, constant, true, NonSI.DEGREE_ANGLE), constant);

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] Tue May  5 16:17:26 2015
@@ -133,6 +133,8 @@ public abstract class MapProjection exte
      * @param  descriptor The descriptor that specify the parameter to validate.
      * @param  value The parameter value in the units given by the descriptor.
      * @throws IllegalArgumentException if the given value is out of bounds.
+     *
+     * @see #createConstant(ParameterBuilder, Double)
      */
     public static void validate(final ParameterDescriptor<Double> descriptor, final double value)
             throws IllegalArgumentException
@@ -150,6 +152,8 @@ public abstract class MapProjection exte
              * because of the way the map projection is defined (see e.g. Mercator1SP.LATITUDE_OF_ORIGIN).
              * But in some cases, it would be possible to deal with non-zero values, even if in principle
              * we should not. In such case we let the caller decides.
+             *
+             * Above check should be revisited if createConstant(ParameterBuilder, Double) is modified.
              */
             if ((min instanceof Number && !(value >= ((Number) min).doubleValue())) ||
                 (max instanceof Number && !(value <= ((Number) max).doubleValue())))

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java [UTF-8] Tue May  5 16:17:26 2015
@@ -823,6 +823,7 @@ public class DefaultParameterValue<T> ex
      */
     @Override
     protected String formatTo(final Formatter formatter) {
+        final ParameterDescriptor<T> descriptor = getDescriptor();  // Gives to users a chance to override this property.
         WKTUtilities.appendName(descriptor, formatter, ElementKind.PARAMETER);
         final Unit<?> targetUnit = formatter.toContextualUnit(descriptor.getUnit());
         final Convention convention = formatter.getConvention();
@@ -832,6 +833,7 @@ public class DefaultParameterValue<T> ex
          * If this parameter value does not use the same unit, then we must convert it.
          * Otherwise we can write the value as-is.
          */
+        final Unit<?> unit = getUnit();  // Gives to users a chance to override this property.
         if (isWKT1 && targetUnit != null) {
             double convertedValue;
             try {
@@ -844,6 +846,11 @@ public class DefaultParameterValue<T> ex
             }
             formatter.append(convertedValue);
         } else {
+            final T value = getValue();  // Gives to users a chance to override this property.
+            if (!isWKT1 && (unit == null) && (value instanceof URI || value instanceof URL || value instanceof File)) {
+                formatter.append(value.toString(), null);
+                return "ParameterFile";
+            }
             formatter.appendAny(value);
         }
         /*

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java [UTF-8] Tue May  5 16:17:26 2015
@@ -27,6 +27,7 @@ import java.util.Locale;
 import java.util.TimeZone;
 import java.io.IOException;
 import java.text.Format;
+import java.text.NumberFormat;
 import java.text.FieldPosition;
 import java.text.ParsePosition;
 import java.text.ParseException;
@@ -692,6 +693,9 @@ public class ParameterFormat extends Tab
                          */
                         final Format format = getFormat(value.getClass());
                         if (format != null) {
+                            if (format instanceof NumberFormat && value instanceof Number) {
+                                configure((NumberFormat) format, Math.abs(((Number) value).doubleValue()));
+                            }
                             value = format.format(value, buffer, dummyFP);
                         }
                         table.append(value.toString());
@@ -739,6 +743,42 @@ public class ParameterFormat extends Tab
             }
         }
     }
+
+    /**
+     * Configures the number pattern to use for the given value. The main intend of this method is to ensure that
+     * the map projection scale factor (a value close to 1) is formatted with a sufficient number of fraction digits.
+     * A common default NumberFormat precision is 3 digits, which is not sufficient. For example the scale factor of
+     * Transverse Mercator projections is 0.9996 (4 digits), and the scale factor of "NTF (Paris) / Lambert zone II"
+     * projection is 0.99987742 (8 digits).
+     *
+     * @param format The format to configure.
+     * @param m The absolute value (magnitude) of the value to write.
+     */
+    private static void configure(final NumberFormat format, final double m) {
+        if (format.getMaximumFractionDigits() <= 9) {
+            /*
+             * If the maximum fraction digits is higher than 9, then that value has not been set by this class.
+             * Maybe the user overrides the createFormat(Class<?>) method in his own subclass, in which case we
+             * will respect his wish and not set a lower value here.
+             */
+            final int n;
+            if (m < 10) {
+                n = 9;
+            } else if (m < 1000) {  // No real use case for this threshold yet, but added for more progressive behavior.
+                n = 6;
+            } else {
+                n = 3;
+            }
+            /*
+             * The minimum fraction digits is usually 0. But if we find a higher value (for example because the
+             * user overrides the createFormat(Class<?>) method), then we will respect user's wish and not set
+             * a lower value.
+             */
+            if (n >= format.getMinimumFractionDigits()) {
+                format.setMaximumFractionDigits(n);
+            }
+        }
+    }
 
     /**
      * Implementation of public {@code format(…)} methods for {@code NAME_SUMMARY} content level.

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java [UTF-8] Tue May  5 16:17:26 2015
@@ -432,6 +432,8 @@ public class AbstractIdentifiedObject ex
      *       {@link org.opengis.referencing.datum.Datum},
      *       {@link org.opengis.referencing.datum.Ellipsoid},
      *       {@link org.opengis.referencing.datum.PrimeMeridian},
+     *       {@link org.opengis.referencing.operation.OperationMethod},
+     *       {@link org.opengis.referencing.operation.CoordinateOperation},
      *       {@link org.opengis.parameter.ParameterDescriptor} or
      *       {@link org.opengis.parameter.ParameterDescriptorGroup},
      *       then this method delegates to the {@code castOrCopy(…)} method of the corresponding SIS subclass.

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/SubTypes.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/SubTypes.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/SubTypes.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/SubTypes.java [UTF-8] Tue May  5 16:17:26 2015
@@ -23,6 +23,8 @@ import org.opengis.referencing.crs.Coord
 import org.opengis.referencing.datum.Datum;
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.datum.PrimeMeridian;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.apache.sis.referencing.crs.AbstractCRS;
@@ -31,6 +33,8 @@ import org.apache.sis.referencing.cs.Def
 import org.apache.sis.referencing.datum.AbstractDatum;
 import org.apache.sis.referencing.datum.DefaultEllipsoid;
 import org.apache.sis.referencing.datum.DefaultPrimeMeridian;
+import org.apache.sis.referencing.operation.DefaultOperationMethod;
+import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
 import org.apache.sis.parameter.DefaultParameterDescriptor;
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
 
@@ -47,7 +51,7 @@ import org.apache.sis.parameter.DefaultP
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
 final class SubTypes {
@@ -81,6 +85,12 @@ final class SubTypes {
         if (object instanceof PrimeMeridian) {
             return DefaultPrimeMeridian.castOrCopy((PrimeMeridian) object);
         }
+        if (object instanceof CoordinateOperation) {
+            return AbstractCoordinateOperation.castOrCopy((CoordinateOperation) object);
+        }
+        if (object instanceof OperationMethod) {
+            return DefaultOperationMethod.castOrCopy((OperationMethod) object);
+        }
         if (object instanceof ParameterDescriptor<?>) {
             return DefaultParameterDescriptor.castOrCopy((ParameterDescriptor<?>) object);
         }

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/AbstractCRS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -28,6 +28,7 @@ import org.opengis.referencing.cs.Affine
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.crs.SingleCRS;
+import org.opengis.referencing.crs.GeneralDerivedCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.referencing.AbstractReferenceSystem;
@@ -47,9 +48,17 @@ import org.apache.sis.internal.jdk7.Obje
 
 
 /**
- * Abstract coordinate reference system, usually defined by a coordinate system and a datum.
- * {@code AbstractCRS} can have an arbitrary number of dimensions. The actual dimension of a
- * given instance can be determined as below:
+ * Coordinate reference system, defined by a {@linkplain AbstractCS coordinate system}
+ * and (usually) a {@linkplain org.apache.sis.referencing.datum.AbstractDatum datum}.
+ * A coordinate reference system (CRS) consists of an ordered sequence of
+ * {@linkplain org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis coordinate system axes}
+ * that are related to the earth through the datum.
+ * Most coordinate reference system do not move relative to the earth, except for
+ * {@linkplain DefaultEngineeringCRS engineering coordinate reference systems}
+ * defined on moving platforms such as cars, ships, aircraft, and spacecraft.
+ *
+ * <p>Coordinate reference systems can have an arbitrary number of dimensions.
+ * The actual dimension of a given instance can be determined as below:</p>
  *
  * {@preformat java
  *   int dimension = crs.getCoordinateSystem().getDimension();
@@ -71,7 +80,7 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.6
  * @module
  *
  * @see AbstractCS
@@ -80,6 +89,7 @@ import org.apache.sis.internal.jdk7.Obje
 @XmlType(name="AbstractCRSType")
 @XmlRootElement(name = "AbstractCRS")
 @XmlSeeAlso({
+    AbstractDerivedCRS.class,
     DefaultGeodeticCRS.class,
     DefaultVerticalCRS.class,
     DefaultTemporalCRS.class,
@@ -384,14 +394,6 @@ public class AbstractCRS extends Abstrac
     }
 
     /**
-     * Returns the unit used for all axis, or {@code null} if not all axis uses the same unit.
-     * This method is often used for formatting according  Well Known Text (WKT) version 1.
-     */
-    final Unit<?> getUnit() {
-        return ReferencingUtilities.getUnit(coordinateSystem);
-    }
-
-    /**
      * Compares this coordinate reference system with the specified object for equality.
      * If the {@code mode} argument value is {@link ComparisonMode#STRICT STRICT} or
      * {@link ComparisonMode#BY_CONTRACT BY_CONTRACT}, then all available properties are
@@ -458,20 +460,55 @@ public class AbstractCRS extends Abstrac
     @Override
     protected String formatTo(final Formatter formatter) {
         final String  keyword = super.formatTo(formatter);
-        final CoordinateSystem cs = coordinateSystem;
-        final boolean isWKT1  = formatter.getConvention().majorVersion() == 1;
-        final Unit<?> unit    = ReferencingUtilities.getUnit(cs);
-        final Unit<?> oldUnit = formatter.addContextualUnit(unit);
         formatter.newLine();
         formatter.append(toFormattable(getDatum()));
         formatter.newLine();
+        final boolean isWKT1 = formatter.getConvention().majorVersion() == 1;
+        if (isWKT1 || !isBaseCRS(formatter)) {
+            formatCS(formatter, getCoordinateSystem(), isWKT1);
+        }
+        return keyword;
+    }
+
+    /**
+     * Returns {@code true} if the given formatter is in the process of formatting the base CRS of a
+     * {@link AbstractDerivedCRS}. In such case, the coordinate system axes shall not be formatted.
+     *
+     * <p>This method should return {@code true} when {@code this} CRS is the value returned by
+     * {@link GeneralDerivedCRS#getBaseCRS()} (typically {@link AbstractDerivedCRS#getBaseCRS()}).
+     * Since the base CRS is the only CRS enclosed in derived CRS, we should have no ambiguity
+     * (assuming that the user did not created some weird subclass).</p>
+     *
+     * <p>This method should be invoked for WKT 2 formatting only.</p>
+     */
+    static boolean isBaseCRS(final Formatter formatter) {
+        return formatter.getEnclosingElement(1) instanceof GeneralDerivedCRS;
+    }
+
+    /**
+     * Formats the given coordinate system.
+     *
+     * <p>In WKT 2 format, this method should not be invoked if {@link #isBaseCRS(Formatter)} returned {@code true}
+     * because ISO 19162 excludes the coordinate system definition in base CRS. Note however that WKT 1 includes the
+     * coordinate systems.</p>
+     *
+     * @param formatter The formatter where to append the coordinate system.
+     * @param cs        The coordinate system to append.
+     * @param isWKT1    {@code true} if formatting WKT 1, or {@code false} for WKT 2.
+     */
+    final void formatCS(final Formatter formatter, final CoordinateSystem cs, final boolean isWKT1) {
+        assert (formatter.getConvention().majorVersion() == 1) == isWKT1 : isWKT1;
+        assert isWKT1 || !isBaseCRS(formatter) : isWKT1;    // Condition documented in javadoc.
+
+        final Unit<?> unit    = ReferencingUtilities.getUnit(cs);
+        final Unit<?> oldUnit = formatter.addContextualUnit(unit);
         if (isWKT1) { // WKT 1 writes unit before axes, while WKT 2 writes them after axes.
             formatter.append(unit);
             if (unit == null) {
                 formatter.setInvalidWKT(this, null);
             }
         } else {
-            formatter.append(toFormattable(cs)); // The concept of CoordinateSystem was not explicit in WKT 1.
+            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();
@@ -487,6 +524,5 @@ public class AbstractCRS extends Abstrac
         formatter.removeContextualUnit(unit);
         formatter.addContextualUnit(oldUnit);
         formatter.newLine(); // For writing the ID[…] element on its own line.
-        return keyword;
     }
 }

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -424,7 +424,7 @@ public class DefaultCompoundCRS extends
         final Convention convention = formatter.getConvention();
         final boolean isWKT1 = convention.majorVersion() == 1;
         for (final CoordinateReferenceSystem element :
-                (isWKT1 || convention == Convention.INTERNAL) ? components : singles)
+                (isWKT1 || convention == Convention.INTERNAL) ? getComponents() : getSingleComponents())
         {
             formatter.newLine();
             formatter.append(toFormattable(element));

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -62,7 +62,7 @@ import static org.apache.sis.util.Argume
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
 @XmlType(name = "EngineeringCRSType", propOrder = {
@@ -85,7 +85,7 @@ public class DefaultEngineeringCRS exten
     /**
      * The datum.
      */
-    @XmlElement(name = "engineeringDatum")
+    @XmlElement(name = "engineeringDatum", required = true)
     private final EngineeringDatum datum;
 
     /**
@@ -260,6 +260,7 @@ public class DefaultEngineeringCRS exten
     @Override
     protected String formatTo(final Formatter formatter) {
         super.formatTo(formatter);
-        return (formatter.getConvention().majorVersion() == 1) ? "Local_CS" : "EngineeringCRS";
+        return (formatter.getConvention().majorVersion() == 1) ? "Local_CS"
+               : isBaseCRS(formatter) ? "BaseEngCRS" : "EngineeringCRS";
     }
 }

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -245,7 +245,7 @@ public class DefaultGeocentricCRS extend
      *   GEOCCS["Geocentric",
      *     DATUM["World Geodetic System 1984",
      *       SPHEROID["WGS84", 6378137.0, 298.257223563]],
-     *     PRIMEM["Greenwich", 0.0],
+     *       PRIMEM["Greenwich", 0.0],
      *     UNIT["metre", 1],
      *     AXIS["X", OTHER],
      *     AXIS["Y", EAST],

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -17,7 +17,7 @@
 package org.apache.sis.referencing.crs;
 
 import java.util.Map;
-import javax.measure.unit.Unit;
+import javax.measure.unit.NonSI;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -27,9 +27,12 @@ import org.opengis.referencing.cs.Ellips
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.datum.GeodeticDatum;
+import org.opengis.referencing.datum.PrimeMeridian;
 import org.apache.sis.internal.referencing.Legacy;
 import org.apache.sis.internal.referencing.WKTUtilities;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.referencing.AbstractReferenceSystem;
+import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.io.wkt.Formatter;
 
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
@@ -68,7 +71,7 @@ class DefaultGeodeticCRS extends Abstrac
     /**
      * The datum.
      */
-    @XmlElement(name = "geodeticDatum")
+    @XmlElement(name = "geodeticDatum", required = true)
     private final GeodeticDatum datum;
 
     /**
@@ -165,68 +168,81 @@ class DefaultGeodeticCRS extends Abstrac
 
     /**
      * Formats this CRS as a <cite>Well Known Text</cite> {@code GeodeticCRS[…]} element.
+     * More information about the WKT format is documented in subclasses.
      *
      * @return {@code "GeodeticCRS"} (WKT 2) or {@code "GeogCS"}/{@code "GeocCS"} (WKT 1).
      */
     @Override
     protected String formatTo(final Formatter formatter) {
         WKTUtilities.appendName(this, formatter, null);
-        final boolean isWKT1  = formatter.getConvention().majorVersion() == 1;
-        final Unit<?> unit    = getUnit();
-        final Unit<?> oldUnit = formatter.addContextualUnit(unit);
+        final Convention convention = formatter.getConvention();
+        final boolean isWKT1 = (convention.majorVersion() == 1);
+        /*
+         * Unconditionally format the datum element, followed by the prime meridian.
+         * The prime meridian is part of datum according ISO 19111, but is formatted
+         * as a sibling (rather than a child) element in WKT for historical reasons.
+         */
+        final GeodeticDatum datum = getDatum();     // Gives subclasses a chance to override.
         formatter.newLine();
         formatter.append(toFormattable(datum));
         formatter.newLine();
-        formatter.indent(isWKT1 ? 0 : +1);
-        formatter.append(toFormattable(datum.getPrimeMeridian()));
-        formatter.indent(isWKT1 ? 0 : -1);
-        formatter.newLine();
-        CoordinateSystem cs = super.getCoordinateSystem();
-        if (isWKT1) { // WKT 1 writes unit before axes, while WKT 2 writes them after axes.
-            formatter.append(unit);
-            if (unit == null) {
-                formatter.setInvalidWKT(this, null);
-            }
-            /*
-             * Replaces the given coordinate system by an instance conform to the conventions used in WKT 1.
-             * Note that we can not delegate this task to subclasses, because XML unmarshalling of a geodetic
-             * CRS will NOT create an instance of a subclass (because the distinction between geographic and
-             * geocentric CRS is not anymore in ISO 19111:2007).
-             */
+        final PrimeMeridian pm = datum.getPrimeMeridian();
+        if (convention != Convention.WKT2_SIMPLIFIED ||
+                ReferencingUtilities.getGreenwichLongitude(pm, NonSI.DEGREE_ANGLE) != 0)
+        {
+            formatter.indent(1);
+            formatter.append(toFormattable(pm));
+            formatter.indent(-1);
+            formatter.newLine();
+        }
+        /*
+         * Get the coordinate system to format. This will also determine the units to write and the keyword to
+         * return in WKT 1 format. Note that for the WKT 1 format, we need to replace the coordinate system by
+         * an instance conform to the legacy conventions.
+         *
+         * We can not delegate the work below to subclasses,  because XML unmarshalling of a geodetic CRS will
+         * NOT create an instance of a subclass (because the distinction between geographic and geocentric CRS
+         * is not anymore in ISO 19111:2007).
+         */
+        CoordinateSystem cs = getCoordinateSystem();
+        final boolean isBaseCRS;
+        if (isWKT1) {
             if (!(cs instanceof EllipsoidalCS)) { // Tested first because this is the most common case.
                 if (cs instanceof CartesianCS) {
                     cs = Legacy.forGeocentricCRS((CartesianCS) cs, true);
                 } else {
-                    formatter.setInvalidWKT(cs, null);
+                    formatter.setInvalidWKT(cs, null);  // SphericalCS was not supported in WKT 1.
                 }
             }
+            isBaseCRS = false;
         } else {
-            formatter.append(toFormattable(cs)); // The concept of CoordinateSystem was not explicit in WKT 1.
-            formatter.indent(+1);
+            isBaseCRS = isBaseCRS(formatter);
         }
-        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();
-            formatter.append(unit);
-            formatter.indent(-1);
-        }
-        formatter.removeContextualUnit(unit);
-        formatter.addContextualUnit(oldUnit);
-        formatter.newLine(); // For writing the ID[…] element on its own line.
-        if (!isWKT1) {
-            return "GeodeticCRS";
+        /*
+         * Format the coordinate system, except if this CRS is the base CRS of an AbstractDerivedCRS in WKT 2 format.
+         * This is because ISO 19162 omits the coordinate system definition of enclosed base CRS in order to simplify
+         * the WKT. The 'formatCS(…)' method may write axis unit before or after the axes depending on whether we are
+         * formatting WKT version 1 or 2 respectively.
+         *
+         * Note that even if we do not format the CS, we may still write the units if we are formatting in "simplified"
+         * mode (as opposed to the more verbose mode). This looks like the opposite of what we would expect, but this is
+         * because formatting the unit here allow us to avoid repeating the unit in projection parameters when this CRS
+         * is part of a ProjectedCRS.
+         */
+        if (!isBaseCRS) {
+            formatCS(formatter, cs, isWKT1);    // Will also format the axis unit.
+        } else if (convention.isSimplified()) {
+            formatter.append(formatter.toContextualUnit(ReferencingUtilities.getAngularUnit(cs)));
         }
         /*
-         * For WKT1, the keyword depends on the subclass: "GeogCS" for GeographicCRS,
-         * or 'GeocCS" for GeocentricCRS. However we can not rely on the subclass for
-         * choosing the keyword, because in some situations (after XML unmarhaling)
-         * we only have a GeodeticCRS. We need to make the choice here. The CS type
-         * is a sufficient criterion.
+         * For WKT 1, the keyword depends on the subclass: "GeogCS" for GeographicCRS or "GeocCS" for GeocentricCRS.
+         * However we can not rely on the subclass for choosing the keyword, because after XML unmarhaling we only
+         * have a GeodeticCRS. We need to make the choice in this base class. The CS type is a sufficient criterion.
          */
-        return (cs instanceof EllipsoidalCS) ? "GeogCS" : "GeocCS";
+        if (isWKT1) {
+            return (cs instanceof EllipsoidalCS) ? "GeogCS" : "GeocCS";
+        } else {
+            return isBaseCRS ? "BaseGeodCRS" : "GeodeticCRS";
+        }
     }
 }

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeographicCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeographicCRS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeographicCRS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultGeographicCRS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -22,6 +22,7 @@ import java.util.Arrays;
 import javax.xml.bind.annotation.XmlTransient;
 import org.opengis.referencing.ReferenceIdentifier;
 import org.opengis.referencing.datum.GeodeticDatum;
+import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.cs.EllipsoidalCS;
 import org.opengis.referencing.cs.CoordinateSystem;
@@ -32,6 +33,7 @@ import org.apache.sis.referencing.cs.Axe
 import org.apache.sis.referencing.AbstractReferenceSystem;
 import org.apache.sis.io.wkt.Formatter;
 import org.apache.sis.measure.Longitude;
+import org.apache.sis.util.resources.Errors;
 
 import static org.apache.sis.internal.util.Constants.CRS;
 import static org.apache.sis.internal.util.Constants.EPSG;
@@ -56,7 +58,7 @@ import static org.apache.sis.internal.ut
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.6
  * @module
  */
 @XmlTransient
@@ -141,6 +143,21 @@ public class DefaultGeographicCRS extend
     }
 
     /**
+     * For {@link SC_GeographicCRS} JAXB adapter only. This is needed because GML does not have "GeographicCRS" type.
+     * Instead, the unmarshalling process will give us a "GeodeticCRS" object with the constraint that the coordinate
+     * system shall be ellipsoidal. This constructor will be invoked for converting the GeodeticCRS instance to a
+     * GeographicCRS instance.
+     */
+    DefaultGeographicCRS(final GeodeticCRS crs) {
+        super(crs);
+        final CoordinateSystem cs = super.getCoordinateSystem();
+        if (!(cs instanceof EllipsoidalCS)) {
+            throw new IllegalArgumentException(Errors.format(
+                    Errors.Keys.IllegalClass_2, EllipsoidalCS.class, cs.getClass()));
+        }
+    }
+
+    /**
      * Constructs a new coordinate reference system with the same values than the specified one.
      * This copy constructor provides a way to convert an arbitrary implementation into a SIS one
      * or a user-defined one (as a subclass), usually in order to leverage some implementation-specific API.
@@ -265,18 +282,18 @@ public class DefaultGeographicCRS extend
      *        AngleUnit["degree", 0.017453292519943295],
      *      Area["World"],
      *      BBox[-90.00, -180.00, 90.00, 180.00],
-     *      Scope["Used by GPS satellite navigation system."]
+     *      Scope["Used by GPS satellite navigation system."],
      *      Id["EPSG", 4326, Citation["IOGP"], URI["urn:ogc:def:crs:EPSG::4326"]]]
      * }
      *
      * <p>Same coordinate reference system using WKT 1.</p>
      *
      * {@preformat wkt
-     *   GEOGCS["WGS 84"
-     *      DATUM["World Geodetic System 1984"
-     *        SPHEROID["WGS84", 6378137.0, 298.257223563]]
-     *      PRIMEM["Greenwich", 0.0]
-     *      UNIT["degree", 0.017453292519943295]
+     *   GEOGCS["WGS 84",
+     *      DATUM["World Geodetic System 1984",
+     *        SPHEROID["WGS84", 6378137.0, 298.257223563]],
+     *        PRIMEM["Greenwich", 0.0],
+     *      UNIT["degree", 0.017453292519943295],
      *      AXIS["Latitude", NORTH],
      *      AXIS["Longitude", EAST],
      *      AUTHORITY["EPSG", "4326"]]

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultImageCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultImageCRS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultImageCRS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultImageCRS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -67,7 +67,7 @@ public class DefaultImageCRS extends Abs
     /**
      * The datum.
      */
-    @XmlElement(name = "imageDatum")
+    @XmlElement(name = "imageDatum", required = true)
     private final ImageDatum datum;
 
     /**
@@ -226,14 +226,14 @@ public class DefaultImageCRS extends Abs
      * Used by JAXB only (invoked by reflection).
      */
     private void setAffineCS(final AffineCS cs) {
-        super.setCoordinateSystem("affineCS", cs);
+        setCoordinateSystem("affineCS", cs);
     }
 
     /**
      * Used by JAXB only (invoked by reflection).
      */
     private void setCartesianCS(final CartesianCS cs) {
-        super.setCoordinateSystem("cartesianCS", cs);
+        setCoordinateSystem("cartesianCS", cs);
     }
 
     /**
@@ -264,12 +264,10 @@ public class DefaultImageCRS extends Abs
      */
     @Override
     protected String formatTo(final Formatter formatter) {
-        /*
-         * Note: super.formatTo(formatter) will usually format a DefaultImageDatum instance,
-         * which will declare this WKT has invalid if the formatter convention is a WKT 1 one.
-         * So we do not redo this check here.
-         */
         super.formatTo(formatter);
+        if (formatter.getConvention().majorVersion() == 1) {
+            formatter.setInvalidWKT(this, null);
+        }
         return "ImageCRS";
     }
 }

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -55,7 +55,7 @@ import static org.apache.sis.util.Argume
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  *
  * @see org.apache.sis.referencing.datum.DefaultTemporalDatum
@@ -75,7 +75,7 @@ public class DefaultTemporalCRS extends
     /**
      * The datum.
      */
-    @XmlElement(name = "temporalDatum")
+    @XmlElement(name = "temporalDatum", required = true)
     private final TemporalDatum datum;
 
     /**
@@ -229,7 +229,7 @@ public class DefaultTemporalCRS extends
      * @return The coordinate system.
      */
     @Override
-    @XmlElement(name = "timeCS")
+    @XmlElement(name = "timeCS", required = true)
     public TimeCS getCoordinateSystem() {
         return (TimeCS) super.getCoordinateSystem();
     }
@@ -238,7 +238,7 @@ public class DefaultTemporalCRS extends
      * Used by JAXB only (invoked by reflection).
      */
     private void setCoordinateSystem(final TimeCS cs) {
-        super.setCoordinateSystem("timeCS", cs);
+        setCoordinateSystem("timeCS", cs);
     }
 
     /**
@@ -307,12 +307,10 @@ public class DefaultTemporalCRS extends
      */
     @Override
     protected String formatTo(final Formatter formatter) {
-        /*
-         * Note: super.formatTo(formatter) will usually format a DefaultTemporalDatum instance,
-         * which will declare this WKT has invalid if the formatter convention is a WKT 1 one.
-         * So we do not redo this check here.
-         */
         super.formatTo(formatter);
-        return "TimeCRS";
+        if (formatter.getConvention().majorVersion() == 1) {
+            formatter.setInvalidWKT(this, null);
+        }
+        return isBaseCRS(formatter) ? "BaseTimeCRS" : "TimeCRS";
     }
 }

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultVerticalCRS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultVerticalCRS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultVerticalCRS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -47,7 +47,7 @@ import static org.apache.sis.util.Argume
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  *
  * @see org.apache.sis.referencing.datum.DefaultVerticalDatum
@@ -67,7 +67,7 @@ public class DefaultVerticalCRS extends
     /**
      * The datum.
      */
-    @XmlElement(name = "verticalDatum")
+    @XmlElement(name = "verticalDatum", required = true)
     private final VerticalDatum datum;
 
     /**
@@ -200,7 +200,7 @@ public class DefaultVerticalCRS extends
      * @return The coordinate system.
      */
     @Override
-    @XmlElement(name = "verticalCS")
+    @XmlElement(name = "verticalCS", required = true)
     public VerticalCS getCoordinateSystem() {
         return (VerticalCS) super.getCoordinateSystem();
     }
@@ -209,7 +209,7 @@ public class DefaultVerticalCRS extends
      * Used by JAXB only (invoked by reflection).
      */
     private void setCoordinateSystem(final VerticalCS cs) {
-        super.setCoordinateSystem("verticalCS", cs);
+        setCoordinateSystem("verticalCS", cs);
     }
 
     /**
@@ -238,6 +238,7 @@ public class DefaultVerticalCRS extends
     @Override
     protected String formatTo(final Formatter formatter) {
         super.formatTo(formatter);
-        return (formatter.getConvention().majorVersion() == 1) ? "Vert_CS" : "VerticalCRS";
+        return (formatter.getConvention().majorVersion() == 1) ? "Vert_CS"
+               : isBaseCRS(formatter) ? "BaseVertCRS" : "VerticalCRS";
     }
 }

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java [UTF-8] Tue May  5 16:17:26 2015
@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.Comparator;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.CompoundCRS;
+import org.opengis.referencing.crs.DerivedCRS;
 import org.opengis.referencing.crs.EngineeringCRS;
 import org.opengis.referencing.crs.GeocentricCRS;
 import org.opengis.referencing.crs.GeodeticCRS;
@@ -50,7 +51,7 @@ import org.apache.sis.referencing.cs.Axe
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
 final class SubTypes implements Comparator<Object> {
@@ -105,6 +106,12 @@ final class SubTypes implements Comparat
      * @see AbstractCRS#castOrCopy(CoordinateReferenceSystem)
      */
     static AbstractCRS castOrCopy(final CoordinateReferenceSystem object) {
+        if (object instanceof DerivedCRS) {
+            return DefaultDerivedCRS.castOrCopy((DerivedCRS) object);
+        }
+        if (object instanceof ProjectedCRS) {
+            return DefaultProjectedCRS.castOrCopy((ProjectedCRS) object);
+        }
         if (object instanceof GeodeticCRS) {
             if (object instanceof GeographicCRS) {
                 return DefaultGeographicCRS.castOrCopy((GeographicCRS) object);

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/package-info.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/package-info.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/package-info.java [UTF-8] Tue May  5 16:17:26 2015
@@ -74,7 +74,7 @@
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Cédric Briançon (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.6
  * @module
  */
 @XmlSchema(elementFormDefault= XmlNsForm.QUALIFIED, namespace = Namespaces.GML, xmlns = {
@@ -88,8 +88,8 @@
     @XmlJavaTypeAdapter(CD_ImageDatum.class),
     @XmlJavaTypeAdapter(CD_TemporalDatum.class),
     @XmlJavaTypeAdapter(CD_VerticalDatum.class),
+    @XmlJavaTypeAdapter(CS_CartesianCS.class),      // Must be before CS_AffineCS.
     @XmlJavaTypeAdapter(CS_AffineCS.class),
-    @XmlJavaTypeAdapter(CS_CartesianCS.class),
     @XmlJavaTypeAdapter(CS_CylindricalCS.class),
     @XmlJavaTypeAdapter(CS_EllipsoidalCS.class),
     @XmlJavaTypeAdapter(CS_LinearCS.class),
@@ -98,6 +98,8 @@
     @XmlJavaTypeAdapter(CS_TimeCS.class),
     @XmlJavaTypeAdapter(CS_UserDefinedCS.class),
     @XmlJavaTypeAdapter(CS_VerticalCS.class),
+    @XmlJavaTypeAdapter(CC_Conversion.class),
+    @XmlJavaTypeAdapter(SC_GeographicCRS.class),
     @XmlJavaTypeAdapter(StringAdapter.class),
     @XmlJavaTypeAdapter(InternationalStringConverter.class)
 })

Modified: sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java?rev=1677853&r1=1677852&r2=1677853&view=diff
==============================================================================
--- sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java [UTF-8] (original)
+++ sis/branches/Android/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java [UTF-8] Tue May  5 16:17:26 2015
@@ -446,7 +446,7 @@ public class AbstractCS extends Abstract
             formatter.setInvalidWKT(this, null);
         }
         formatter.append(type, null);
-        formatter.append(axes.length);
+        formatter.append(getDimension());
         return "CS";
     }
 }



Mime
View raw message