sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1823786 - in /sis/branches/ISO-19115-3/core/sis-utility/src: main/java/org/apache/sis/xml/ test/java/org/apache/sis/test/suite/ test/java/org/apache/sis/xml/
Date Sat, 10 Feb 2018 17:06:26 GMT
Author: desruisseaux
Date: Sat Feb 10 17:06:26 2018
New Revision: 1823786

URL: http://svn.apache.org/viewvc?rev=1823786&view=rev
Log:
Better mapping from namespace URI to XML prefix.

Added:
    sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/xml/FilteredNamespacesTest.java
  (with props)
Modified:
    sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilterVersion.java
    sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredNamespaces.java
    sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredWriter.java
    sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java

Modified: sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilterVersion.java
URL: http://svn.apache.org/viewvc/sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilterVersion.java?rev=1823786&r1=1823785&r2=1823786&view=diff
==============================================================================
--- sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilterVersion.java
[UTF-8] (original)
+++ sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilterVersion.java
[UTF-8] Sat Feb 10 17:06:26 2018
@@ -43,32 +43,32 @@ enum FilterVersion {
     ISO19139(new String[] {
             Namespaces.CAT,
             Namespaces.CIT,
+            Namespaces.DQC,
+            Namespaces.FCC,
+            Namespaces.GEX,
+            Namespaces.GMW,
             Namespaces.LAN,
             Namespaces.MAC,
             Namespaces.MAS,
             Namespaces.MCC,
             Namespaces.MCO,
+            Namespaces.MD1,
+            Namespaces.MD2,
+            Namespaces.MDA,
+            Namespaces.MDB,
+            Namespaces.MDQ,
+            Namespaces.MDS,
+            Namespaces.MDT,
             Namespaces.MEX,
             Namespaces.MMI,
             Namespaces.MPC,
             Namespaces.MRC,
             Namespaces.MRD,
-            Namespaces.MDQ,
             Namespaces.MRI,
             Namespaces.MRL,
             Namespaces.MRS,
             Namespaces.MSR,
-            Namespaces.MDS,
-            Namespaces.MD1,
-            Namespaces.MDA,
-            Namespaces.MDT,
-            Namespaces.MD2,
-            Namespaces.RCE,
-            Namespaces.FCC,
-            Namespaces.GMW,
-            Namespaces.DQC,
-            Namespaces.MDB,
-            Namespaces.GEX,
+            Namespaces.RCE
         }, LegacyNamespaces.GMD,
         new String[] {
             Namespaces.GCX, LegacyNamespaces.GMX,
@@ -97,26 +97,26 @@ enum FilterVersion {
     ALL(ISO19139, GML31);
 
     /**
-     * The URI replacements to apply when going from the "real" data producer (JAXB marshaller)
-     * to the filtered reader/writer. Keys are the actual URIs as declared in SIS implementation,
-     * and values are the URIs read or to write instead of the actual ones.
+     * The URI replacements to apply when going from the model implemented by Apache SIS
+     * to the filtered reader/writer. Keys are the URIs as declared in JAXB annotations,
+     * and values are the URIs to write instead of the actual ones.
      *
      * @see FilteredNamespaces#exports
      */
     final Map<String,String> exports;
 
     /**
-     * The URI replacements to apply when going from the filtered reader/writer to the "real"
-     * data consumer (JAXB unmarshaller). This map is the converse of {@link #exports}.
+     * The URI replacements to apply when going from the filtered reader/writer to the
+     * model implemented by Apache SIS. This map is the converse of {@link #exports}.
      *
      * @see FilteredNamespaces#imports
      */
     final Map<String,String> imports;
 
     /**
-     * {@code true} if application of {@link #exports} result in many namespaces collapsed
into
-     * a single namespace. In those case, {@link #imports} is not sufficient for performing
the
-     * reverse operation; we need {@link FilteredStreamResolver}.
+     * {@code true} if applying {@link #exports} replacements results in many namespaces
collapsed into
+     * a single namespace. In those case, {@link #imports} is not sufficient for performing
the reverse
+     * operation; we need {@link FilteredStreamResolver}.
      */
     final boolean manyToOne;
 

Modified: sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredNamespaces.java
URL: http://svn.apache.org/viewvc/sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredNamespaces.java?rev=1823786&r1=1823785&r2=1823786&view=diff
==============================================================================
--- sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredNamespaces.java
[UTF-8] (original)
+++ sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredNamespaces.java
[UTF-8] Sat Feb 10 17:06:26 2018
@@ -18,6 +18,7 @@ package org.apache.sis.xml;
 
 import java.util.Map;
 import java.util.Iterator;
+import java.util.NoSuchElementException;
 import javax.xml.namespace.NamespaceContext;
 
 
@@ -111,7 +112,10 @@ final class FilteredNamespaces implement
     }
 
     /**
-     * Returns the namespace for the given prefix.
+     * Returns the namespace for the given prefix. The same URI may be returned for many
prefixes.
+     * For example when exporting from ISO 19115-3:2016 to legacy ISO 19139:2007, the {@code
"mdb"},
+     * {@code "cit"} and many other prefixes are all mapped to {@code "http://www.isotc211.org/2005/gmd"}.
+     * This is legal according {@link NamespaceContext} javadoc.
      */
     @Override
     public String getNamespaceURI(final String prefix) {
@@ -120,19 +124,104 @@ final class FilteredNamespaces implement
     }
 
     /**
-     * Returns the prefix for the given namespace.
+     * Returns an arbitrary prefix for the given namespace. More than one prefix may be bounded
to a namespace,
+     * in which case this method returns an arbitrary prefix (which may differ between different
JVM executions).
      */
     @Override
     public String getPrefix(final String namespaceURI) {
-        return context.getPrefix(imports.getOrDefault(namespaceURI, namespaceURI));
+        final String ns = imports.get(namespaceURI);
+        if (ns != null) {
+            final String p = context.getPrefix(ns);
+            if (p != null) return p;
+        }
+        /*
+         * We can not use the 'imports' map when the same namespace (e.g. "http://www.isotc211.org/2005/gmd"
from
+         * legacy ISO 19139:2007) is mapped to multiple namespaces in the new ISO 19115-3:2016
or other standard.
+         * In such case, we have to iterate over map 'exports' entries until we find an inverse
mapping.
+         */
+        for (final Map.Entry<String,String> e : exports.entrySet()) {
+            if (namespaceURI.equals(e.getValue())) {
+                final String p = context.getPrefix(e.getKey());
+                if (p != null) return p;
+            }
+        }
+        return context.getPrefix(namespaceURI);
     }
 
     /**
-     * Returns all prefixes for the given namespace.
+     * Returns all prefixes for the given namespace. For example given the {@code "http://www.isotc211.org/2005/gmd"}
+     * namespace from legacy ISO 19139:2007, this method returns {@code "mdb"}, {@code "cit"}
and all other prefixes
+     * from the new ISO 19115-3:2016 specification which are used in replacement of the legacy
{@code "gmd"} prefix.
      */
     @Override
-    @SuppressWarnings("unchecked")          // TODO: remove on JDK9
     public Iterator<String> getPrefixes(final String namespaceURI) {
-        return context.getPrefixes(imports.getOrDefault(namespaceURI, namespaceURI));
+        return new Prefixes(context, exports, namespaceURI);
+    }
+
+    /**
+     * Iterator for the prefixes to be returned by {@link FilteredNamespaces#getPrefixes(String)}.
+     * Each prefix is fetched only when first needed.
+     */
+    private static final class Prefixes implements Iterator<String> {
+        /** The namespace for which prefixes are desired. */
+        private final String namespaceURI;
+
+        /** The {@link FilteredNamespaces#context} reference. */
+        private final NamespaceContext context;
+
+        /** Iterator over the {@link FilteredNamespaces#exports} entries. */
+        private final Iterator<Map.Entry<String,String>> exports;
+
+        /** Iterator over some (not all) prefixes, or {@code null} if a new iterator needs
to be fetched. */
+        private Iterator<String> prefixes;
+
+        /** The next value to be returned by {@link #next()}, or {@code null} if not yet
fetched. */
+        private String next;
+
+        /** Creates a new iterator for the prefixes associated to the given namespace URI.
*/
+        Prefixes(final NamespaceContext context, final Map<String,String> exports,
final String namespaceURI) {
+            this.context      = context;
+            this.exports      = exports.entrySet().iterator();
+            this.namespaceURI = namespaceURI;
+        }
+
+        /**
+         * Returns {@code true} if there is at least one more prefix to return.
+         * Invoking this method fetched at most one prefix from the wrapped context.
+         */
+        @Override
+        @SuppressWarnings("unchecked")          // TODO: remove on JDK9
+        public boolean hasNext() {
+            while (next == null) {
+                while (prefixes == null) {
+                    if (!exports.hasNext()) {
+                        return false;
+                    }
+                    final Map.Entry<String,String> e = exports.next();
+                    if (namespaceURI.equals(e.getValue())) {
+                        prefixes = context.getPrefixes(e.getKey());
+                    }
+                }
+                if (prefixes.hasNext()) {
+                    next = prefixes.next();
+                } else {
+                    prefixes = null;
+                }
+            }
+            return true;
+        }
+
+        /**
+         * Returns the next prefix.
+         */
+        @Override
+        public String next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+            final String n = next;
+            next = null;
+            return n;
+        }
     }
 }

Modified: sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredWriter.java
URL: http://svn.apache.org/viewvc/sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredWriter.java?rev=1823786&r1=1823785&r2=1823786&view=diff
==============================================================================
--- sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredWriter.java
[UTF-8] (original)
+++ sis/branches/ISO-19115-3/core/sis-utility/src/main/java/org/apache/sis/xml/FilteredWriter.java
[UTF-8] Sat Feb 10 17:06:26 2018
@@ -92,7 +92,7 @@ final class FilteredWriter implements XM
      * Returns the URI to write in the XML document.
      * If there is no namespace change, then this method returns the given instance as-is.
      */
-    private String export(final String uri) {
+    private String exportNS(final String uri) {
         return version.exports.getOrDefault(uri, uri);
     }
 
@@ -258,7 +258,7 @@ final class FilteredWriter implements XM
      */
     @Override
     public String getPrefix(final String uri) throws XMLStreamException {
-        return out.getPrefix(export(uri));
+        return out.getPrefix(exportNS(uri));
     }
 
     /**
@@ -267,7 +267,7 @@ final class FilteredWriter implements XM
      */
     @Override
     public void setPrefix(final String prefix, final String uri) throws XMLStreamException
{
-        out.setPrefix(prefix, export(uri));
+        out.setPrefix(prefix, exportNS(uri));
     }
 
     /**
@@ -276,7 +276,7 @@ final class FilteredWriter implements XM
      */
     @Override
     public void setDefaultNamespace(final String uri) throws XMLStreamException {
-        out.setDefaultNamespace(export(uri));
+        out.setDefaultNamespace(exportNS(uri));
     }
 
     /**

Modified: sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1823786&r1=1823785&r2=1823786&view=diff
==============================================================================
--- sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
[UTF-8] (original)
+++ sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
[UTF-8] Sat Feb 10 17:06:26 2018
@@ -150,6 +150,7 @@ import org.junit.BeforeClass;
     org.apache.sis.xml.ValueConverterTest.class,
     org.apache.sis.xml.OGCNamespacePrefixMapperTest.class,
     org.apache.sis.xml.MarshallerPoolTest.class,
+    org.apache.sis.xml.FilteredNamespacesTest.class,
     org.apache.sis.internal.jaxb.XmlUtilitiesTest.class,
     org.apache.sis.internal.jaxb.IdentifierMapAdapterTest.class,
     org.apache.sis.internal.jaxb.ModifiableIdentifierMapTest.class,

Added: sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/xml/FilteredNamespacesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/xml/FilteredNamespacesTest.java?rev=1823786&view=auto
==============================================================================
--- sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/xml/FilteredNamespacesTest.java
(added)
+++ sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/xml/FilteredNamespacesTest.java
[UTF-8] Sat Feb 10 17:06:26 2018
@@ -0,0 +1,139 @@
+/*
+ * 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.xml;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Collection;
+import java.util.Collections;
+import javax.xml.namespace.NamespaceContext;
+import org.apache.sis.internal.jaxb.LegacyNamespaces;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.apache.sis.test.Assert.*;
+
+
+/**
+ * Tests {@link FilteredNamespaces}.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+public final strictfp class FilteredNamespacesTest extends TestCase implements NamespaceContext
{
+    /**
+     * All prefixes declared in this test.
+     */
+    private static Collection<String> prefixes() {
+        return Arrays.asList("mdq", "ns1", "ns2", "cit", "mdb", "gex");
+    }
+
+    /**
+     * Tests {@link FilteredNamespaces#getPrefixes(String)}.
+     */
+    @Test
+    public void testGetPrefixes() {
+        final FilteredNamespaces fns = new FilteredNamespaces(this, FilterVersion.ISO19139,
false);
+        final Iterator<String> it = fns.getPrefixes(LegacyNamespaces.GMD);
+        final Set<String> prefixes = new HashSet<>();
+        while (it.hasNext()) {
+            assertTrue(prefixes.add(it.next()));
+        }
+        assertSetEquals(prefixes(), prefixes);
+    }
+
+    /**
+     * Dummy implementation of {@link NamespaceContext#getPrefixes(String)} for {@link #testGetPrefixes()}
purpose.
+     * This method will be invoked many times by the prefix iterator implemented by {@link
FilteredNamespaces}.
+     * This method implementation uses a hard-coded list of arbitrary prefixes.
+     *
+     * @param  namespaceURI  the namespace for which to get one or more prefixes.
+     * @return prefixes for the given namespace.
+     */
+    @Override
+    public Iterator<String> getPrefixes(final String namespaceURI) {
+        final Collection<String> prefixes;
+        switch (namespaceURI) {
+            case Namespaces.MDQ: {
+                // Arbitrarily return more than one prefix for that namespace.
+                prefixes = Arrays.asList("mdq", "ns1", "ns2");
+                break;
+            }
+            default: {
+                final String p = getPrefix(namespaceURI);
+                prefixes = (p != null) ? Collections.singleton(p) : Collections.emptySet();
+                break;
+            }
+        }
+        return prefixes.iterator();
+    }
+
+    /**
+     * Tests {@link FilteredNamespaces#getPrefix(String)}.
+     */
+    @Test
+    public void testGetPrefix() {
+        final FilteredNamespaces fns = new FilteredNamespaces(this, FilterVersion.ISO19139,
false);
+        /*
+         * Following tests are not really interesting since FilteredNamespaces,
+         * after failing to find a mapping, just delegates to this.getPrefix(…).
+         */
+        assertEquals("cit", fns.getPrefix(Namespaces.CIT));
+        assertEquals("mdb", fns.getPrefix(Namespaces.MDB));
+        assertEquals("gex", fns.getPrefix(Namespaces.GEX));
+        /*
+         * This is the interesting test: FilteredNamespaces replaces the gmd namespace
+         * by one of the namespace recognized by this NamespaceContext, then delegates.
+         */
+        assertNull(getPrefix(LegacyNamespaces.GMD));                // This test is useless
if this is non-null.
+        final String prefix = fns.getPrefix(LegacyNamespaces.GMD);
+        assertTrue(prefix, prefixes().contains(prefix));
+    }
+
+    /**
+     * Dummy implementation of {@link NamespaceContext#getPrefix(String)} for {@link #testGetPrefix()}
purpose.
+     * This method will be invoked many times by the prefix iterator implemented by {@link
FilteredNamespaces}.
+     * This method implementation uses a hard-coded list of arbitrary prefixes.
+     *
+     * @param  namespaceURI  the namespace for which to get an arbitrary prefixes.
+     * @return a prefix for the given namespace.
+     */
+    @Override
+    public String getPrefix(final String namespaceURI) {
+        switch (namespaceURI) {
+            case Namespaces.CIT: return "cit";
+            case Namespaces.MDB: return "mdb";
+            case Namespaces.GEX: return "gex";
+            default: return null;
+        }
+    }
+
+    /**
+     * Not needed for this test.
+     *
+     * @param  prefix  ignored.
+     * @return never return.
+     */
+    @Override
+    public String getNamespaceURI(String prefix) {
+        throw new UnsupportedOperationException();
+    }
+}

Propchange: sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/xml/FilteredNamespacesTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/ISO-19115-3/core/sis-utility/src/test/java/org/apache/sis/xml/FilteredNamespacesTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8



Mime
View raw message