sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1793281 - in /sis/branches/JDK8: core/sis-metadata/src/main/java/org/apache/sis/io/wkt/ core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ core/sis-referencing/src/main/java/org/apache/sis/referencing/ core/sis-referen...
Date Sun, 30 Apr 2017 23:31:09 GMT
Author: desruisseaux
Date: Sun Apr 30 23:31:09 2017
New Revision: 1793281

URL: http://svn.apache.org/viewvc?rev=1793281&view=rev
Log:
CRS.fromWKT(String) and CRS.fromXML(String) should compare the parsed definition with the
authoritative definition (if an authority code is available) and log a warning if a conflict
is found.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DefinitionVerifier.java
  (with props)
Modified:
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Parser.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MissingFactoryResourceException.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/UnavailableFactoryException.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListeners.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/Store.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java

Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/AbstractParser.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -197,8 +197,8 @@ abstract class AbstractParser implements
     }
 
     /**
-     * Creates the object from a string. This method is for implementation of {@code createFromWKT(String)}
-     * method is SIS factories only.
+     * Creates the object from a string and log the warnings if any.
+     * This method is for implementation of {@code createFromWKT(String)} method is SIS factories
only.
      *
      * @param  text  coordinate system encoded in Well-Known Text format (version 1 or 2).
      * @return the result of parsing the given text.

Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Parser.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Parser.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Parser.java [UTF-8]
(original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Parser.java [UTF-8]
Sun Apr 30 23:31:09 2017
@@ -37,6 +37,12 @@ import org.opengis.util.FactoryException
  *   <li>{@link org.apache.sis.geometry.Envelopes#fromWKT(CharSequence)}</li>
  * </ul>
  *
+ * Non-fatal anomalies found in Well Known Texts are reported in a {@linkplain java.util.logging.Logger
logger}
+ * named {@code "org.apache.sis.io.wkt"}. Warnings may be for unknown or unsupported WKT
elements, inconsistent
+ * unit definitions (unit symbol, scale factor or EPSG code), unparsable axis abbreviations,
<i>etc.</i>
+ * However this parser does not verify if the overall parsed object matches the EPSG (or
other authority) definition.
+ * For such verification, see {@link org.apache.sis.referencing.CRS#fromWKT(String)}.
+ *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 0.6
  * @since   0.6
@@ -48,6 +54,12 @@ public interface Parser {
      * Objects returned by this method are typically (but not necessarily)
      * {@linkplain org.apache.sis.referencing.crs.AbstractCRS Coordinate Reference Systems}
or
      * {@linkplain org.apache.sis.referencing.operation.transform.AbstractMathTransform Math
Transforms}.
+     * If the given text contains non-fatal anomalies, warnings may be reported in a
+     * {@linkplain java.util.logging.Logger logger} named {@code "org.apache.sis.io.wkt"}.
+     *
+     * <div class="note"><b>Tip:</b>
+     * for processing warnings in a different way than logging them, one can use
+     * {@link WKTFormat#parseObject(String)} followed by a call to {@link WKTFormat#getWarnings()}.</div>
      *
      * @param  text  object encoded in Well-Known Text format (version 1 or 2).
      * @return the result of parsing the given text.

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DefinitionVerifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DefinitionVerifier.java?rev=1793281&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DefinitionVerifier.java
(added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DefinitionVerifier.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -0,0 +1,287 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.referencing;
+
+import java.util.Iterator;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import org.opengis.util.FactoryException;
+import org.opengis.metadata.citation.Citation;
+import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.referencing.crs.CRSAuthorityFactory;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.GeneralDerivedCRS;
+import org.opengis.referencing.crs.SingleCRS;
+import org.opengis.referencing.operation.Conversion;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.crs.AbstractCRS;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.cs.AxesConvention;
+import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
+import org.apache.sis.referencing.factory.IdentifiedObjectFinder;
+import org.apache.sis.internal.util.Citations;
+import org.apache.sis.util.logging.Logging;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.Utilities;
+
+
+/**
+ * Verifies the conformance of a given CRS with an authoritative definition.
+ * For example if a Well Known Text (WKT) contains an EPSG code, this class verifies that
+ * the CRS created from the WKT is equivalent to the CRS identified by the authority code.
+ * {@code DefinitionVerifier} contains two informations:
+ *
+ * <ul>
+ *   <li>The recommended CRS to use. May be the given CRS or a CRS created from the
authority factory.</li>
+ *   <li>Warnings if the given CRS does not match the authoritative definition.</li>
+ * </ul>
+ *
+ * <b>Note:</b> ISO 19162 said about the {@code Identifier} keyword:  <cite>"In
the event of conflict in values given
+ * in the CRS WKT string and given by an authority through an object’s name or an identifier,
reading software should
+ * throw an exception or give users a warning message. The WKT values should be assumed to
prevail."</cite>
+ * In practice when such conflicts happen, we often see that the given WKT string contains
mistakes and the
+ * provider intended to use the authoritative definition. We nevertheless comply with ISO
19162 requirement,
+ * but provide a "recommended CRS" field for what we think is the intended CRS.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
+ */
+public final class DefinitionVerifier {
+    /**
+     * List of CRS variants to try if the given CRS does not match the expected definition.
+     * For performance reason, this list should be ordered with most probable variant first
+     * and less probable variant last.
+     */
+    private static final AxesConvention[] VARIANTS = {
+        AxesConvention.NORMALIZED,
+        AxesConvention.CONVENTIONALLY_ORIENTED,
+        AxesConvention.RIGHT_HANDED
+    };
+
+    /**
+     * Recommended CRS. May be the instance given to the {@link #withAuthority withAuthority(…)}
method
+     * or an instance created from the authority factory.
+     *
+     * Note that ISO 19162 said <cite>"Should any attributes or values given in the
cited identifier be in conflict
+     * with attributes or values given explicitly in the WKT description, the WKT values
shall prevail."</cite>
+     * So we normally do not use this field.
+     */
+    public final CoordinateReferenceSystem authoritative;
+
+    /**
+     * If {@link #withAuthority withAuthority(…)} produced a localizable warning, the resource
key for creating the
+     * actual message. A value of 0 means that the warning is already localized and stored
in {@code arguments[0]}.
+     */
+    private short resourceKey;
+
+    /**
+     * The arguments to use together with {@link #resourceKey} for producing the warning
message.
+     */
+    private Object[] arguments;
+
+    /**
+     * Creates the result of a call to {@code withAuthority(…)}.
+     */
+    private DefinitionVerifier(final CoordinateReferenceSystem authoritative) {
+        this.authoritative = authoritative;
+    }
+
+    /**
+     * Compares the given CRS definition with the authoritative definition.
+     * If the comparison produces a warning, a message will be recorded to the given logger.
+     *
+     * @param  crs     the CRS to compare with the authoritative definition.
+     * @param  logger  the logger where to report warnings, if any.
+     * @param  classe  the class to declare as the source of the warning.
+     * @param  method  the method to declare as the source of the warning.
+     * @throws FactoryException if an error occurred while querying the authority factory.
+     */
+    public static void withAuthority(final CoordinateReferenceSystem crs, final String logger,
+            final Class<?> classe, final String method) throws FactoryException
+    {
+        final DefinitionVerifier verification = DefinitionVerifier.withAuthority(crs, null,
false);
+        if (verification != null) {
+            final LogRecord record = verification.warning(true);
+            if (record != null) {
+                record.setLoggerName(logger);
+                Logging.log(classe, method, record);
+            }
+        }
+    }
+
+    /**
+     * Compares the given CRS definition with the authoritative definition.
+     * The authoritative definition is inferred from the identifier, if any.
+     *
+     * @param  crs      the CRS to compare with the authoritative definition.
+     * @param  factory  the factory to use for fetching authoritative definition, or {@code
null} for the default.
+     * @param  lookup   whether this method is allowed to use {@link IdentifiedObjectFinder}.
+     * @return verification result, or {@code null} if the given CRS should be used as-is.
+     * @throws FactoryException if an error occurred while querying the authority factory.
+     */
+    public static DefinitionVerifier withAuthority(final CoordinateReferenceSystem crs, final
CRSAuthorityFactory factory,
+            final boolean lookup) throws FactoryException
+    {
+        final CoordinateReferenceSystem authoritative;
+        final Citation authority = (factory != null) ? factory.getAuthority() : null;
+        final String identifier = IdentifiedObjects.toString(IdentifiedObjects.getIdentifier(crs,
authority));
+        if (identifier != null) try {
+            /*
+             * An authority code was explicitly given in the CRS definition. Create a CRS
for that code
+             * (do not try to guess it). If the given code is unknown, we will report a warning
and use
+             * the given CRS as-is.
+             */
+            if (factory != null) {
+                authoritative = factory.createCoordinateReferenceSystem(identifier);
+            } else {
+                authoritative = CRS.forCode(identifier);
+            }
+        } catch (NoSuchAuthorityCodeException e) {
+            final DefinitionVerifier verifier = new DefinitionVerifier(crs);
+            verifier.arguments = new String[] {e.getLocalizedMessage()};
+            return verifier;
+        } else if (lookup) {
+            /*
+             * No authority code was given in the CRS definition. Try to guess the code with
IdentifiedObjectFinder,
+             * ignoring axis order. If we can not guess a code or if we guess wrongly, use
the given CRS silently
+             * (without reporting any warning) since there is apparently nothing wrong in
the given CRS.
+             */
+            final IdentifiedObjectFinder finder;
+            if (factory instanceof GeodeticAuthorityFactory) {
+                finder = ((GeodeticAuthorityFactory) factory).newIdentifiedObjectFinder();
+            } else {
+                finder = IdentifiedObjects.newFinder(Citations.getIdentifier(authority, false));
+            }
+            finder.setIgnoringAxes(true);
+            finder.setSearchDomain(IdentifiedObjectFinder.Domain.DECLARATION);
+            final IdentifiedObject ref = finder.findSingleton(crs);
+            if (ref instanceof CoordinateReferenceSystem) {
+                authoritative = (CoordinateReferenceSystem) ref;
+            } else {
+                return null;                                            // Found no identifier.
Use the CRS as-is.
+            }
+        } else {
+            return null;
+        }
+        /*
+         * At this point we found an authoritative definition (typically from EPSG database)
for the given CRS.
+         * Verify if the given CRS is equal to the authoritative definition, or a variant
of it. The similarity
+         * variable tells us if we have equality (0), mismatch (-), or equality when using
a variant (+).
+         */
+        int similarity = 0;
+        final AbstractCRS ca = AbstractCRS.castOrCopy(authoritative);
+        AbstractCRS variant = ca;
+        while (!variant.equals(crs, ComparisonMode.APPROXIMATIVE)) {
+            if (similarity < VARIANTS.length) {
+                variant = ca.forConvention(VARIANTS[similarity++]);
+            } else if (identifier == null) {
+                return null;        // Mismatched CRS, but our "authoritative" definition
was only a guess. Ignore.
+            } else {
+                similarity = -1;    // Mismatched CRS and our authoritative definition was
not a guess. Need warning.
+                break;
+            }
+        }
+        final DefinitionVerifier verifier;
+        if (similarity > 0) {
+            /*
+             * Warning message (from Resources.properties):
+             *
+             *     The coordinate system axes in the given “{0}” definition do not conform
to the expected axes
+             *     according “{1}” authoritative definition.
+             */
+            verifier = new DefinitionVerifier(variant);
+            verifier.resourceKey = Resources.Keys.NonConformAxes_2;
+            verifier.arguments   = new String[2];
+        } else {
+            verifier = new DefinitionVerifier(authoritative);
+            if (similarity != 0) {
+                /*
+                 * Warning message (from Resources.properties):
+                 *
+                 *     The given “{0}” definition does not conform to the “{1}” authoritative
definition.
+                 *     Differences are found in {2,choice,0#method|1#conversion|2#coordinate
system|3#datum|4#CRS}.
+                 */
+                verifier.resourceKey  = Resources.Keys.NonConformCRS_3;
+                verifier.arguments    = new Object[3];
+                verifier.arguments[2] = diffCode(CRS.getSingleComponents(authoritative).iterator(),
+                                                 CRS.getSingleComponents(crs).iterator());
+            }
+        }
+        if (verifier.arguments != null) {
+            verifier.arguments[0] = IdentifiedObjects.getName(crs, null);
+            verifier.arguments[1] = IdentifiedObjects.getIdentifierOrName(authoritative);
+        }
+        return verifier;
+    }
+
+    /**
+     * Indicates in which part of CRS definition a difference has been found. Numerical values
must match the number
+     * in the {@code {choice}} instruction in the message associated to {@link Resources.Keys#NonConformCRS_3}.
+     */
+    private static final int METHOD=0, CONVERSION=1, CS=2, DATUM=3, OTHER=4;
+
+    /**
+     * Returns a code indicating in which part the two given CRS differ. The given iterators
usually iterate over
+     * exactly one element, but may iterate over more elements if the CRS were instance of
{@code CompoundCRS}.
+     * The returned value is one of {@link #METHOD}, {@link #CONVERSION}, {@link #CS}, {@link
#DATUM} or
+     * {@link #OTHER} constants.
+     */
+    private static int diffCode(final Iterator<SingleCRS> authoritative, final Iterator<SingleCRS>
crs) {
+        while (authoritative.hasNext() && crs.hasNext()) {
+            final SingleCRS ai = authoritative.next();
+            final SingleCRS ci = crs.next();
+            if (!Utilities.equalsApproximatively(ai, ci)) {
+                if (ai instanceof GeneralDerivedCRS && ci instanceof GeneralDerivedCRS)
{
+                    final Conversion ac = ((GeneralDerivedCRS) ai).getConversionFromBase();
+                    final Conversion gc = ((GeneralDerivedCRS) ci).getConversionFromBase();
+                    if (!Utilities.equalsApproximatively(ac, gc)) {
+                        return Utilities.equalsApproximatively(ac.getMethod(), gc.getMethod())
? CONVERSION : METHOD;
+                    }
+                }
+                if (!Utilities.equalsApproximatively(ai.getCoordinateSystem(), ci.getCoordinateSystem()))
{
+                    return CS;
+                }
+                if (!Utilities.equalsApproximatively(ai.getDatum(), ci.getDatum())) {
+                    return DATUM;
+                }
+                break;
+            }
+        }
+        return OTHER;
+    }
+
+    /**
+     * Returns the warning to log, or {@code null} if none. The caller is responsible for
setting the logger name,
+     * source class name and source method name.
+     *
+     * @param  fine  {@code true} for including warnings at fine level, or {@code false} for
only the warning level.
+     * @return the warning to log, or {@code null} if none.
+     */
+    public LogRecord warning(final boolean fine) {
+        if (arguments != null) {
+            if (resourceKey != 0) {
+                return Resources.forLocale(null).getLogRecord(Level.WARNING, resourceKey,
arguments);
+            } else if (fine) {
+                return new LogRecord(Level.FINE, (String) arguments[0]);
+            }
+        }
+        return null;
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DefinitionVerifier.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DefinitionVerifier.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -321,6 +321,19 @@ public final class Resources extends Ind
         public static final short NoSuchOperationMethod_1 = 50;
 
         /**
+         * The coordinate system axes in the given “{0}” definition do not conform to
the expected axes
+         * according “{1}” authoritative definition.
+         */
+        public static final short NonConformAxes_2 = 72;
+
+        /**
+         * The given “{0}” definition does not conform to the “{1}” authoritative
definition.
+         * Differences are found in {2,choice,0#conversion method|1#conversion definition|2#coordinate
+         * system|3#datum|4#CRS}.
+         */
+        public static final short NonConformCRS_3 = 73;
+
+        /**
          * No horizontal component found in the “{0}” coordinate reference system.
          */
         public static final short NonHorizontalCRS_1 = 71;

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
[ISO-8859-1] Sun Apr 30 23:31:09 2017
@@ -35,6 +35,9 @@ MismatchedEllipsoidAxisLength_3   = The
 MismatchedOperationFactories_2    = No coordinate operation from \u201c{0}\u201d to \u201c{1}\u201d
because of mismatched factories.
 MisnamedParameter_1               = Despite its name, this parameter is effectively \u201c{0}\u201d.
 NotFormalProjectionParameter_1    = This parameter borrowed from the \u201c{0}\u201d projection
is not formally a parameter of this projection.
+NonConformAxes_2                  = The coordinate system axes in the given \u201c{0}\u201d
definition do not conform to the expected axes according \u201c{1}\u201d authoritative definition.
+NonConformCRS_3                   = The given \u201c{0}\u201d definition does not conform
to the \u201c{1}\u201d authoritative definition. \
+                                    Differences are found in {2,choice,0#conversion method|1#conversion
definition|2#coordinate system|3#datum|4#CRS}.
 
 #
 # Error messages (to be used in exceptions)

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
[ISO-8859-1] Sun Apr 30 23:31:09 2017
@@ -40,6 +40,9 @@ MismatchedEllipsoidAxisLength_3   = Le p
 MismatchedOperationFactories_2    = Il n\u2019y a pas d\u2019op\u00e9rations allant de \u00ab\u202f{0}\u202f\u00bb
vers \u00ab\u202f{1}\u202f\u00bb parce que ces derniers sont associ\u00e9s \u00e0 deux fabriques
diff\u00e9rentes.
 MisnamedParameter_1               = Malgr\u00e9 son nom, ce param\u00e8tre produit en r\u00e9alit\u00e9
l\u2019effet d\u2019un \u00ab\u202f{0}\u202f\u00bb.
 NotFormalProjectionParameter_1    = Ce param\u00e8tre emprunt\u00e9 \u00e0 la projection
\u00ab\u202f{0}\u202f\u00bb n\u2019est pas formellement un param\u00e8tre de cette projection.
+NonConformAxes_2                  = Les axes du syst\u00e8me de coordonn\u00e9es d\u00e9finis
dans \u00ab\u202f{0}\u202f\u00bb ne sont pas conformes aux axes attendus d\u2019apr\u00e8s
la d\u00e9finition officielle de \u00ab\u202f{1}\u202f\u00bb.
+NonConformCRS_3                   = La d\u00e9finition donn\u00e9e pour \u00ab\u202f{0}\u202f\u00bb
n\u2019est pas conforme \u00e0 la d\u00e9finition officielle de \u00ab\u202f{1}\u202f\u00bb.
\
+                                    Des diff\u00e9rences ont \u00e9t\u00e9 trouv\u00e9es
dans {2,choice,0#la m\u00e9thode de conversion|1#la d\u00e9finition de la conversion|2#le
syst\u00e8me de coordonn\u00e9es|3#le r\u00e9f\u00e9rentiel|4#le CRS}.
 
 #
 # Error messages (to be used in exceptions)

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -55,8 +55,10 @@ import org.apache.sis.internal.metadata.
 import org.apache.sis.internal.referencing.PositionalAccuracyConstant;
 import org.apache.sis.internal.referencing.CoordinateOperations;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
+import org.apache.sis.internal.referencing.DefinitionVerifier;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.system.Modules;
+import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.referencing.cs.DefaultVerticalCS;
 import org.apache.sis.referencing.cs.DefaultEllipsoidalCS;
 import org.apache.sis.referencing.crs.DefaultGeographicCRS;
@@ -232,7 +234,11 @@ public final class CRS extends Static {
      * }
      * </div>
      *
-     * <div class="section">Usage and performance considerations</div>
+     * If the parsing produced warnings, they will be reported in a logger named {@code "org.apache.sis.io.wkt"}.
+     * In particular, this method verifies if the definition provided by the WKT matches
the definition provided
+     * by the authority ({@code "EPSG:5641"} in above example) and reports discrepancies.
+     *
+     * <div class="note"><b>Usage and performance considerations</b>
      * 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:
@@ -244,7 +250,7 @@ public final class CRS extends Static {
      * </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.
+     * the {@link org.apache.sis.io.wkt.WKTFormat} class instead than this method.</div>
      *
      * @param  text  coordinate system encoded in Well-Known Text format (version 1 or 2).
      * @return the parsed Coordinate Reference System.
@@ -258,7 +264,9 @@ public final class CRS extends Static {
      */
     public static CoordinateReferenceSystem fromWKT(final String text) throws FactoryException
{
         ArgumentChecks.ensureNonNull("text", text);
-        return DefaultFactories.forBuildin(CRSFactory.class).createFromWKT(text);
+        final CoordinateReferenceSystem crs = DefaultFactories.forBuildin(CRSFactory.class).createFromWKT(text);
+        DefinitionVerifier.withAuthority(crs, Loggers.WKT, CRS.class, "fromWKT");
+        return crs;
     }
 
     /**
@@ -277,7 +285,9 @@ public final class CRS extends Static {
      */
     public static CoordinateReferenceSystem fromXML(final String xml) throws FactoryException
{
         ArgumentChecks.ensureNonNull("text", xml);
-        return DefaultFactories.forBuildin(CRSFactory.class).createFromXML(xml);
+        final CoordinateReferenceSystem crs = DefaultFactories.forBuildin(CRSFactory.class).createFromXML(xml);
+        DefinitionVerifier.withAuthority(crs, Loggers.XML, CRS.class, "fromXML");
+        return crs;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -1594,6 +1594,13 @@ public class GeodeticObjectFactory exten
      * }
      * </div>
      *
+     * If the given text contains non-fatal anomalies
+     * (unknown or unsupported WKT elements, inconsistent unit definitions, unparsable axis
abbreviations, <i>etc.</i>),
+     * warnings may be reported in a {@linkplain java.util.logging.Logger logger} named {@code
"org.apache.sis.io.wkt"}.
+     * However this parser does not verify if the overall parsed object matches the EPSG
(or other authority) definition,
+     * since this geodetic object factory is not an {@linkplain GeodeticAuthorityFactory
authority factory}.
+     * For such verification, see the {@link org.apache.sis.referencing.CRS#fromWKT(String)}
convenience method.
+     *
      * <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,

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MissingFactoryResourceException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MissingFactoryResourceException.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MissingFactoryResourceException.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MissingFactoryResourceException.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -20,7 +20,7 @@ import org.opengis.util.FactoryException
 
 
 /**
- * Thrown when an object can not be created because a resource is missing.
+ * Thrown when a particular object can not be created because a resource is missing.
  * The most common case is a NADCON or NTv2 datum shift operation requested while the
  * datum shift grids was not found in the {@code $SIS_DATA/DatumChanges} directory.
  *

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/UnavailableFactoryException.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/UnavailableFactoryException.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/UnavailableFactoryException.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/UnavailableFactoryException.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -20,7 +20,7 @@ import org.opengis.referencing.Authority
 
 
 /**
- * Thrown when a factory can not be created because a resource is missing.
+ * Thrown when a whole factory can not be created because a resource is missing.
  * The most common case is when the {@link org.apache.sis.referencing.factory.sql.EPSGFactory}
  * has no connection to an EPSG database.
  *

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -1313,6 +1313,9 @@ public class DefaultMathTransformFactory
      * Creates a math transform object from a
      * <a href="http://www.geoapi.org/snapshot/javadoc/org/opengis/referencing/doc-files/WKT.html"><cite>Well
      * Known Text</cite> (WKT)</a>.
+     * If the given text contains non-fatal anomalies (unknown or unsupported WKT elements,
+     * inconsistent unit definitions, <i>etc.</i>), warnings may be reported
in a
+     * {@linkplain java.util.logging.Logger logger} named {@code "org.apache.sis.io.wkt"}.
      *
      * @param  text  math transform encoded in Well-Known Text format.
      * @return the math transform (never {@code null}).

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListeners.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListeners.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListeners.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListeners.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -120,19 +120,39 @@ public class WarningListeners<S> impleme
     }
 
     /**
-     * Returns the logger where to send the warnings. The default implementation returns
a logger for
-     * the package name of the {@code source} object. Subclasses should override this method
if they
-     * can provide a fixed logger instance (typically a static final constant).
+     * Returns the logger where to send the warnings when no other destination is specified.
+     * This logger is used when:
      *
-     * @return  the logger where to send the warnings when there is no registered listeners.
+     * <ul>
+     *   <li>no listener has been {@linkplain #addWarningListener registered}, and</li>
+     *   <li>the {@code LogRecord} does not {@linkplain LogRecord#getLoggerName() specify
a logger}.</li>
+     * </ul>
+     *
+     * The default implementation derives a logger for the package name of the {@code source}
object.
+     * Subclasses should override this method if they can provide a more determinist logger
instance,
+     * typically from a static final constant.
+     *
+     * @return the logger where to send the warnings when there is no other destination.
      */
     public Logger getLogger() {
         return Logging.getLogger(source.getClass());
     }
 
     /**
-     * Reports a warning represented by the given log record. The default implementation
notifies the listeners
-     * if any, or logs the message to the logger returned by {@link #getLogger()} otherwise.
+     * Reports a warning represented by the given log record.
+     * The default implementation performs the following choice:
+     *
+     * <ul>
+     *   <li>If at least one listener has been {@linkplain #addWarningListener registered},
then those listeners
+     *       will be notified by a call to {@link WarningListener#warningOccured(Object,
LogRecord)}.</li>
+     *   <li>Otherwise:
+     *     <ul>
+     *       <li>If the value returned by {@link LogRecord#getLoggerName()} is non-null,
+     *           then the warning will be logged to that named logger.</li>
+     *       <li>Otherwise the warning will be logged to the logger given by {@link
#getLogger()}.</li>
+     *     </ul>
+     *   </li>
+     * </ul>
      *
      * @param record  the warning as a log record.
      */
@@ -146,8 +166,14 @@ public class WarningListeners<S> impleme
                 listener.warningOccured(source, record);
             }
         } else {
-            final Logger logger = getLogger();
-            record.setLoggerName(logger.getName());
+            final String name = record.getLoggerName();
+            final Logger logger;
+            if (name != null) {
+                logger = Logging.getLogger(name);
+            } else {
+                logger = getLogger();
+                record.setLoggerName(logger.getName());
+            }
             if (record instanceof QuietLogRecord) {
                 ((QuietLogRecord) record).clearThrown();
             }

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -26,14 +26,18 @@ import java.io.IOException;
 import java.text.ParsePosition;
 import java.text.ParseException;
 import org.opengis.metadata.Metadata;
+import org.opengis.util.FactoryException;
 import org.opengis.referencing.ReferenceSystem;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.internal.storage.Resources;
+import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.io.wkt.WKTFormat;
 import org.apache.sis.io.wkt.Warnings;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
+import org.apache.sis.internal.referencing.DefinitionVerifier;
 import org.apache.sis.metadata.iso.DefaultMetadata;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.CharSequences;
@@ -118,17 +122,35 @@ final class Store extends DataStore {
             } finally {
                 in.close();
             }
+            /*
+             * At this point we copied all the file content into a String. This string usually
contain exactly
+             * one WKT definitions, but this DataStore nevertheless allows an arbitrary number
of consecutive
+             * definitions.
+             */
             final ParsePosition pos = new ParsePosition(0);
             final WKTFormat parser = new WKTFormat(null, null);
             do {
-                objects.add(parser.parse(wkt, pos));
+                final Object obj = parser.parse(wkt, pos);
+                objects.add(obj);
                 pos.setIndex(CharSequences.skipLeadingWhitespaces(wkt, pos.getIndex(), wkt.length()));
                 final Warnings warnings = parser.getWarnings();
                 if (warnings != null) {
-                    final LogRecord record = new LogRecord(Level.WARNING, warnings.toString());
-                    record.setSourceClassName(Store.class.getName());
-                    record.setSourceMethodName("getMetadata");          // Public facade
for this method.
-                    listeners.warning(record);
+                    log(new LogRecord(Level.WARNING, warnings.toString()));
+                }
+                /*
+                 * The WKT has been parsed. Below is a verification of whether the parsed
WKT is conform with
+                 * the authority definition (if an authority code has been specified). This
verification is not
+                 * really necessary since we will use the WKT definition anyway even if we
find discrepancies.
+                 * But non-conform WKT definitions happen so often in practice that we are
better to check.
+                 */
+                if (obj instanceof CoordinateReferenceSystem) try {
+                    final DefinitionVerifier v = DefinitionVerifier.withAuthority((CoordinateReferenceSystem)
obj, null, false);
+                    if (v != null) {
+                        final LogRecord warning = v.warning(false);
+                        if (warning != null) log(warning);
+                    }
+                } catch (FactoryException e) {
+                    listeners.warning(null, e);
                 }
             } while (pos.getIndex() < wkt.length());
         } catch (ParseException e) {
@@ -139,6 +161,16 @@ final class Store extends DataStore {
     }
 
     /**
+     * Reports a warning.
+     */
+    private void log(final LogRecord record) {
+        record.setSourceClassName(Store.class.getName());
+        record.setSourceMethodName("getMetadata");          // Public facade for the parse()
method.
+        record.setLoggerName(Loggers.WKT);
+        listeners.warning(record);
+    }
+
+    /**
      * Returns the metadata associated to the parsed objects, or {@code null} if none.
      * The current implementation retains only instances of {@link ReferenceSystem}
      * and ignore other cases.

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/Store.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/Store.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/Store.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/Store.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -26,7 +26,9 @@ import java.io.IOException;
 import javax.xml.bind.JAXBException;
 import javax.xml.transform.stream.StreamSource;
 import org.opengis.metadata.Metadata;
+import org.opengis.util.FactoryException;
 import org.opengis.referencing.ReferenceSystem;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.xml.XML;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.StorageConnector;
@@ -34,6 +36,8 @@ import org.apache.sis.storage.DataStoreE
 import org.apache.sis.metadata.iso.DefaultMetadata;
 import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.internal.referencing.DefinitionVerifier;
 
 import static java.util.Collections.singleton;
 
@@ -124,6 +128,7 @@ final class Store extends DataStore {
 
                 /** Reports the occurrence of a non-fatal error during XML unmarshalling.
*/
                 @Override public void warningOccured(final Object source, final LogRecord
warning) {
+                    warning.setLoggerName(Loggers.XML);
                     listeners.warning(warning);
                 }
             });
@@ -150,6 +155,26 @@ final class Store extends DataStore {
         } catch (JAXBException | IOException e) {
             throw new DataStoreException(Errors.format(Errors.Keys.CanNotRead_1, getDisplayName()),
e);
         }
+        if (object instanceof CoordinateReferenceSystem) try {
+            final DefinitionVerifier v = DefinitionVerifier.withAuthority((CoordinateReferenceSystem)
object, null, false);
+            if (v != null) {
+                log(v.warning(false));
+            }
+        } catch (FactoryException e) {
+            listeners.warning(null, e);
+        }
+    }
+
+    /**
+     * Reports a warning, if non-null.
+     */
+    private void log(final LogRecord record) {
+        if (record != null) {
+            record.setSourceClassName(Store.class.getName());
+            record.setSourceMethodName("getMetadata");          // Public facade for the
parse() method.
+            record.setLoggerName(Loggers.XML);
+            listeners.warning(record);
+        }
     }
 
     /**

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java?rev=1793281&r1=1793280&r2=1793281&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java
[UTF-8] Sun Apr 30 23:31:09 2017
@@ -335,7 +335,8 @@ public abstract class StaxDataStore exte
         @Override
         public void report(String message, String errorType, Object info, Location location)
{
             final LogRecord record = new LogRecord(Level.WARNING, message);
-            record.setSourceClassName(getClass().getCanonicalName());
+            record.setSourceClassName(StaxDataStore.this.getClass().getCanonicalName());
+            // record.setLoggerName(…) will be invoked by 'listeners' with inferred name.
             listeners.warning(record);
         }
 
@@ -347,6 +348,7 @@ public abstract class StaxDataStore exte
          */
         @Override
         public void warningOccured(final Object source, final LogRecord warning) {
+            warning.setLoggerName(null);        // For allowing 'listeners' to select a logger
name.
             listeners.warning(warning);
         }
 



Mime
View raw message