sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1779902 - in /sis/branches/JDK8: core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/lineage/ core/sis-metadata/src/test/resources/org/apache/sis/metadata/iso/lineag...
Date Mon, 23 Jan 2017 10:55:29 GMT
Author: desruisseaux
Date: Mon Jan 23 10:55:29 2017
New Revision: 1779902

URL: http://svn.apache.org/viewvc?rev=1779902&view=rev
Log:
XML.marshal(...) now convert implementation of GeoAPI interfaces that are not the default
implementation.
This allows us to marshall GPX metadata in ISO 19139 format.

Modified:
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataTypes.java
    sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStepTest.java
    sis/branches/JDK8/core/sis-metadata/src/test/resources/org/apache/sis/metadata/iso/lineage/ProcessStep.xml
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingTypes.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/converter/ConverterRegistry.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java
    sis/branches/JDK8/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java

Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataTypes.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataTypes.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataTypes.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataTypes.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -17,8 +17,24 @@
 package org.apache.sis.internal.metadata;
 
 import java.util.Collection;
+import org.opengis.metadata.Metadata;
+import org.opengis.metadata.content.Band;
+import org.opengis.metadata.content.ImageDescription;
+import org.opengis.metadata.lineage.ProcessStep;
+import org.opengis.metadata.lineage.Source;
 import org.apache.sis.internal.jaxb.TypeRegistration;
+import org.apache.sis.internal.jaxb.gmi.LE_ProcessStep;
+import org.apache.sis.internal.jaxb.gmi.LE_Source;
+import org.apache.sis.internal.jaxb.gmi.MI_Band;
+import org.apache.sis.internal.jaxb.gmi.MI_CoverageDescription;
+import org.apache.sis.internal.jaxb.gmi.MI_Georectified;
+import org.apache.sis.internal.jaxb.gmi.MI_Georeferenceable;
+import org.apache.sis.internal.jaxb.gmi.MI_ImageDescription;
+import org.apache.sis.internal.jaxb.gmi.MI_Metadata;
 import org.apache.sis.metadata.iso.DefaultMetadata;
+import org.opengis.metadata.content.CoverageDescription;
+import org.opengis.metadata.spatial.Georectified;
+import org.opengis.metadata.spatial.Georeferenceable;
 
 
 /**
@@ -27,7 +43,7 @@ import org.apache.sis.metadata.iso.Defau
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.8
  * @module
  */
 public final class MetadataTypes extends TypeRegistration {
@@ -35,7 +51,45 @@ public final class MetadataTypes extends
      * Adds to the given collection the metadata types that should be given to the initial
JAXB context.
      */
     @Override
-    public void getTypes(final Collection<Class<?>> addTo) {
+    protected void getTypes(final Collection<Class<?>> addTo) {
         addTo.add(DefaultMetadata.class);
     }
+
+    /**
+     * Notifies that the {@code sis-metadata} module can marshal arbitrary implementations
of some metadata interfaces.
+     *
+     * @return {@code true}.
+     */
+    @Override
+    protected boolean canMarshalInterfaces() {
+        return true;
+    }
+
+    /**
+     * Ensures that the given value is an instance of a class that can be marshalled, or
returns {@code null}
+     * if the type of the given value is not handled by this method. Current implementation
handles all types
+     * that may need to be put in the ISO 19115-3 namespace; we have to do that ourself because
those classes
+     * are not public. Other types may be added if needed, but we do not want to handle too
many of them (for
+     * performance reasons). However the list or recognized types shall contain at least
{@link Metadata}.
+     *
+     * @param  value  the value to marshal.
+     * @return the given value as a type that can be marshalled, or {@code null}.
+     */
+    @Override
+    public Object toImplementation(final Object value) {
+        /*
+         * Classes that are most likely to be used should be checked first.  If a type is
a specialization
+         * of another type (e.g. ImageDescription extends CoverageDescription), the specialized
type shall
+         * be before the more generic type.
+         */
+        if (value instanceof Metadata)            return MI_Metadata           .castOrCopy((Metadata)
           value);
+        if (value instanceof ImageDescription)    return MI_ImageDescription   .castOrCopy((ImageDescription)
   value);
+        if (value instanceof CoverageDescription) return MI_CoverageDescription.castOrCopy((CoverageDescription)
value);
+        if (value instanceof Georectified)        return MI_Georectified       .castOrCopy((Georectified)
       value);
+        if (value instanceof Georeferenceable)    return MI_Georeferenceable   .castOrCopy((Georeferenceable)
   value);
+        if (value instanceof Band)                return MI_Band               .castOrCopy((Band)
               value);
+        if (value instanceof ProcessStep)         return LE_ProcessStep        .castOrCopy((ProcessStep)
        value);
+        if (value instanceof Source)              return LE_Source             .castOrCopy((Source)
             value);
+        return null;
+    }
 }

Modified: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStepTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStepTest.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStepTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/lineage/DefaultProcessStepTest.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -18,10 +18,11 @@ package org.apache.sis.metadata.iso.line
 
 import javax.xml.bind.JAXBException;
 import org.apache.sis.util.iso.SimpleInternationalString;
+import org.apache.sis.internal.jaxb.gmi.LE_ProcessStep;
 import org.apache.sis.test.XMLTestCase;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static org.opengis.test.Assert.*;
 
 
 /**
@@ -30,7 +31,7 @@ import static org.junit.Assert.*;
  * @author  Cédric Briançon (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.8
  * @module
  */
 public final strictfp class DefaultProcessStepTest extends XMLTestCase {
@@ -59,7 +60,13 @@ public final strictfp class DefaultProce
         assertMarshalEqualsFile(XML_FILE, processStep, "xlmns:*", "xsi:schemaLocation");
         /*
          * XML unmarshalling: ensure that we didn't lost any information.
+         * Note that since the XML uses the <gmi:…> namespace, we got an instance
of LE_ProcessStep, which
+         * in SIS implementation does not carry any useful information; it is just a consequence
of the way
+         * namespaces are managed. We will convert to the parent DefaultProcessStep type
before comparison.
          */
-        assertEquals(processStep, unmarshalFile(DefaultProcessStep.class, XML_FILE));
+        DefaultProcessStep step = unmarshalFile(DefaultProcessStep.class, XML_FILE);
+        assertInstanceOf("The unmarshalled object is expected to be in GMI namespace.", LE_ProcessStep.class,
step);
+        step = new DefaultProcessStep(step);
+        assertEquals(processStep, step);
     }
 }

Modified: sis/branches/JDK8/core/sis-metadata/src/test/resources/org/apache/sis/metadata/iso/lineage/ProcessStep.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/resources/org/apache/sis/metadata/iso/lineage/ProcessStep.xml?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/resources/org/apache/sis/metadata/iso/lineage/ProcessStep.xml
(original)
+++ sis/branches/JDK8/core/sis-metadata/src/test/resources/org/apache/sis/metadata/iso/lineage/ProcessStep.xml
Mon Jan 23 10:55:29 2017
@@ -18,7 +18,7 @@
   under the License.
 -->
 
-<gmd:LI_ProcessStep
+<gmi:LE_ProcessStep
     xmlns:gmd = "http://www.isotc211.org/2005/gmd"
     xmlns:gco = "http://www.isotc211.org/2005/gco"
     xmlns:gmi = "http://www.isotc211.org/2005/gmi"
@@ -39,4 +39,4 @@
       </gmi:procedureDescription>
     </gmi:LE_Processing>
   </gmi:processingInformation>
-</gmd:LI_ProcessStep>
+</gmi:LE_ProcessStep>

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingTypes.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingTypes.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingTypes.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingTypes.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -21,6 +21,8 @@ import org.apache.sis.internal.jaxb.Type
 import org.apache.sis.parameter.DefaultParameterValue;
 import org.apache.sis.parameter.DefaultParameterValueGroup;
 import org.apache.sis.referencing.AbstractIdentifiedObject;
+import org.apache.sis.referencing.AbstractReferenceSystem;
+import org.opengis.referencing.ReferenceSystem;
 
 
 /**
@@ -29,7 +31,7 @@ import org.apache.sis.referencing.Abstra
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.8
  * @module
  */
 public final class ReferencingTypes extends TypeRegistration {
@@ -37,9 +39,32 @@ public final class ReferencingTypes exte
      * Adds to the given collection the referencing types that should be given to the initial
JAXB context.
      */
     @Override
-    public void getTypes(final Collection<Class<?>> addTo) {
+    protected void getTypes(final Collection<Class<?>> addTo) {
         addTo.add(AbstractIdentifiedObject.class);
         addTo.add(DefaultParameterValue.class);
         addTo.add(DefaultParameterValueGroup.class);
     }
+
+    /**
+     * Notifies that the {@code sis-referencing} module can marshal arbitrary implementations
+     * of some coordinate reference system interfaces.
+     *
+     * @return {@code true}.
+     */
+    @Override
+    protected boolean canMarshalInterfaces() {
+        return true;
+    }
+
+    /**
+     * Ensures that the given value is an instance of a class that can be marshalled,
+     * or returns {@code null} if the type is not handled by this method.
+     *
+     * @param  value  the value to marshal.
+     * @return the given value as a type that can be marshalled, or {@code null}.
+     */
+    @Override
+    public Object toImplementation(final Object value) {
+        return (value instanceof ReferenceSystem) ? AbstractReferenceSystem.castOrCopy((ReferenceSystem)
value) : null;
+    }
 }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/converter/ConverterRegistry.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/converter/ConverterRegistry.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/converter/ConverterRegistry.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/converter/ConverterRegistry.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -132,7 +132,7 @@ public class ConverterRegistry {
      */
     @SuppressWarnings("unchecked")
     private <S,T> void put(ClassPair<S,T> key, final ObjectConverter<? super
S, ? extends T> converter) {
-        assert key.getClass() == ClassPair.class; // See SystemConverter.equals(Object)
+        assert key.getClass() == ClassPair.class;                   // See SystemConverter.equals(Object)
         assert key.cast(converter) != null : converter;
         assert Thread.holdsLock(converters);
         if (converter instanceof SystemConverter<?,?> &&
@@ -269,7 +269,7 @@ public class ConverterRegistry {
              * for the place where to put the given converter in the hierarchy of converters.
              */
             if (!isInitialized) {
-                isInitialized = true; // Before 'initialize()' for preventing infinite recursivity.
+                isInitialized = true;           // Before 'initialize()' for preventing infinite
recursivity.
                 initialize();
             }
             for (Class<? super T> i=targetClass; i!=null && i!=stopAt; i=i.getSuperclass())
{
@@ -354,7 +354,7 @@ public class ConverterRegistry {
              * its source is more specific:  the source of 'converter' is of type <S>
while the
              * source of 'existing' is of type <? super S>.
              */
-            assert converter.getSourceClass() == key.sourceClass; // Enforced by parameterized
type.
+            assert converter.getSourceClass() == key.sourceClass;       // Enforced by parameterized
type.
             if (existing.getSourceClass() == key.sourceClass) {
                 final boolean oldIsExact = isExactlyFor(existing,  key.targetClass);
                 final boolean newIsExact = isExactlyFor(converter, key.targetClass);
@@ -374,7 +374,7 @@ public class ConverterRegistry {
                      * checked the source class in the above 'if' statement.
                      */
                     converter = FallbackConverter.merge((ObjectConverter<S, ? extends
T>) existing, converter);
-                    assert key.targetClass.isAssignableFrom(converter.getTargetClass()) :
converter; // See FallbackConverter.merge javadoc.
+                    assert key.targetClass.isAssignableFrom(converter.getTargetClass()) :
converter;    // See FallbackConverter.merge javadoc.
                 }
             }
         }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -16,8 +16,11 @@
  */
 package org.apache.sis.internal.jaxb;
 
+import java.util.Map;
+import java.util.HashMap;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import javax.xml.bind.JAXBContext;
@@ -47,14 +50,37 @@ import org.apache.sis.internal.system.De
  */
 public abstract class TypeRegistration {
     /**
+     * Undocumented (for now) marshaller property for specifying conversions to apply on
root objects
+     * before marshalling. Conversions are applied by the {@link #toImplementation(Object)}
method.
+     *
+     * @see #addDefaultRootAdapters(Map)
+     */
+    public static final String ROOT_ADAPTERS = "org.apache.sis.xml.rootAdapters";
+
+    /**
      * The JAXB context, or {@code null} if not yet created or if the classpath changed.
+     *
+     * @see #getSharedContext()
      */
     private static Reference<JAXBContext> context;
+
+    /**
+     * The {@link TypeRegistration} instances found on the classpath for which the
+     * {@link #toImplementation(Object)} method has been overridden.
+     *
+     * @see #addDefaultRootAdapters(Map)
+     */
+    private static TypeRegistration[] converters;
+
+    /**
+     * Forces reloading of JAXB context and converters if the classpath changes.
+     */
     static {
         SystemListener.add(new SystemListener(Modules.UTILITIES) {
             @Override protected void classpathChanged() {
                 synchronized (TypeRegistration.class) {
-                    context = null;
+                    context    = null;
+                    converters = null;
                 }
             }
         });
@@ -67,39 +93,83 @@ public abstract class TypeRegistration {
     }
 
     /**
-     * Adds to the given collection every types that should be given to
-     * the initial JAXB context.
+     * Adds to the given collection every types that should be given to the initial JAXB
context.
+     * The types added by this method include only implementation classes having JAXB annotations.
+     * If the module can also marshal arbitrary implementations of some interfaces (e.g.
GeoAPI),
+     * then the {@link #canMarshalInterfaces()} method should be overridden.
      *
      * @param  addTo  the collection in which to add new types.
      */
-    public abstract void getTypes(final Collection<Class<?>> addTo);
+    protected abstract void getTypes(final Collection<Class<?>> addTo);
+
+    /**
+     * Returns {@code true} if the module can also marshal arbitrary implementation of some
interfaces.
+     * If this method returns {@code true}, then the {@link #toImplementation(Object)} method
shall be
+     * overridden.
+     *
+     * @return whether the module can also marshal arbitrary implementation of some interfaces.
+     *
+     * @since 0.8
+     */
+    protected boolean canMarshalInterfaces() {
+        return false;
+    }
 
     /**
-     * Returns the root classes of SIS objects to be marshalled by default.
-     * Those classes can be given as the last argument to the {@code MarshallerPool}
-     * constructors, in order to bound a default set of classes with {@code JAXBContext}.
+     * If the given value needs to be converted before marshalling, apply the conversion
now.
+     * Otherwise returns {@code null} if the value class is not recognized, or {@code value}
+     * if the class is recognized but the value does not need to be changed.
+     *
+     * <p>Subclasses that override this method will typically perform an {@code instanceof}
check, then
+     * invoke one of the {@code castOrCopy(…)} static methods defined in various Apache
SIS classes.</p>
+     *
+     * <p>This method is invoked only if {@link #canMarshalInterfaces()} returns {@code
true}.</p>
      *
-     * <p>The list of classes is determined dynamically from the SIS modules found
on
-     * the classpath.</p>
+     * @param  value  the value to convert before marshalling.
+     * @return the value to marshall; or {@code null} if this method does not recognize
the value class.
+     * @throws JAXBException if an error occurred while converting the given object.
      *
-     * @return the default set of classes to be bound to the {@code JAXBContext}.
+     * @since 0.8
      */
-    private static Class<?>[] defaultClassesToBeBound() {
+    public Object toImplementation(final Object value) throws JAXBException {
+        return null;
+    }
+
+    /**
+     * Scans the classpath for root classes to put in JAXB context and for converters to
those classes.
+     * Those lists are determined dynamically from the SIS modules found on the classpath.
+     * The list of root classes is created only if the {@code getTypes} argument is {@code
true}.
+     *
+     * @param  getTypes  whether to get the root classes to put in JAXB context (may cause
class loading).
+     * @return if {@code getTypes} was {@code true}, the root classes to be bound in {@code
JAXBContext}.
+     */
+    private static Class<?>[] load(final boolean getTypes) {
         /*
          * Implementation note: do not keep the ServiceLoader in static field because:
          *
-         * 1) It would cache the TypeRegistration instances, which are not needed after this
method call.
+         * 1) It would cache more TypeRegistration instances than needed for this method
call.
          * 2) The ClassLoader between different invocations may be different in an OSGi context.
          */
         final ArrayList<Class<?>> types = new ArrayList<>();
-        for (final TypeRegistration t : DefaultFactories.createServiceLoader(TypeRegistration.class))
{
-            t.getTypes(types);
+        final ArrayList<TypeRegistration> toImpl = (converters == null) ? new ArrayList<>()
: null;
+        if (toImpl != null || getTypes) {
+            for (final TypeRegistration t : DefaultFactories.createServiceLoader(TypeRegistration.class))
{
+                if (getTypes) {
+                    t.getTypes(types);
+                }
+                if (toImpl != null && t.canMarshalInterfaces()) {
+                    toImpl.add(t);
+                }
+            }
+            if (toImpl != null) {
+                converters = toImpl.toArray(new TypeRegistration[toImpl.size()]);
+            }
         }
         return types.toArray(new Class<?>[types.size()]);
     }
 
     /**
-     * Returns the shared {@code JAXBContext} for the set of {@link #defaultClassesToBeBound()}.
+     * Returns the shared {@code JAXBContext} for the set of {@link #load()}.
      * Note that the {@code JAXBContext} class is thread safe, but the {@code Marshaller},
      * {@code Unmarshaller}, and {@code Validator} classes are not thread safe.
      *
@@ -114,8 +184,43 @@ public abstract class TypeRegistration {
                 return instance;
             }
         }
-        final JAXBContext instance = JAXBContext.newInstance(defaultClassesToBeBound());
+        final JAXBContext instance = JAXBContext.newInstance(load(true));
         context = new WeakReference<>(instance);
         return instance;
     }
+
+    /**
+     * Completes the given properties with an entry for {@link #ROOT_ADAPTERS} if not already
present.
+     * If a {@code ROOT_ADAPTERS} entry is already present, then the map is returned unchanged.
+     *
+     * <p>This method store a direct reference to the internal {@code TypeRegistration[]}
array in the given map.
+     * <strong>That array shall not be modified.</strong> This method is currently
for Apache SIS internal usage only,
+     * because the {@code TypeRegistration} class is not part of public API. However if we
add this functionality in a
+     * future SIS release (probably as an interface rather than exposing {@code TypeRegistration}
itself), then we may
+     * consider removing this method.</p>
+     *
+     * @param  properties  the properties to complete.
+     * @return the given properties with the {@link #ROOT_ADAPTERS} entry added.
+     *
+     * @since 0.8
+     */
+    public static Map<String,?> addDefaultRootAdapters(final Map<String,?> properties)
{
+        if (properties != null && properties.containsKey(ROOT_ADAPTERS)) {
+            return properties;
+        }
+        TypeRegistration[] c;
+        synchronized (TypeRegistration.class) {
+            c = converters;
+            if (c == null) {
+                load(false);
+                c = converters;
+            }
+        }
+        if (properties == null) {
+            return Collections.singletonMap(ROOT_ADAPTERS, c);
+        }
+        final Map<String,Object> copy = new HashMap<>(properties);
+        copy.put(ROOT_ADAPTERS, c);
+        return copy;
+    }
 }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -164,7 +164,12 @@ public class MarshallerPool {
      * @throws JAXBException if the JAXB context can not be created.
      */
     public MarshallerPool(final Map<String,?> properties) throws JAXBException {
-        this(TypeRegistration.getSharedContext(), properties);
+        /*
+         * We currently add the default root adapters only when using the JAXB context provided
by Apache SIS.
+         * We presume that if the user specified his own JAXBContext, then he does not expect
us to change the
+         * classes that he wants to marshal.
+         */
+        this(TypeRegistration.getSharedContext(), TypeRegistration.addDefaultRootAdapters(properties));
     }
 
     /**
@@ -243,8 +248,10 @@ public class MarshallerPool {
         try {
             ((Pooled) marshaller).reset(template);
         } catch (JAXBException exception) {
-            // Not expected to happen because we are supposed
-            // to reset the properties to their initial values.
+            /*
+             * Not expected to happen because we are supposed
+             * to reset the properties to their initial values.
+             */
             Logging.unexpectedException(Logging.getLogger(Loggers.XML), MarshallerPool.class,
"recycle", exception);
             return;
         }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java [UTF-8]
(original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/Pooled.java [UTF-8]
Mon Jan 23 10:55:29 2017
@@ -38,6 +38,7 @@ import org.apache.sis.util.logging.Warni
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.internal.jaxb.LegacyNamespaces;
+import org.apache.sis.internal.jaxb.TypeRegistration;
 
 
 /**
@@ -156,6 +157,14 @@ abstract class Pooled {
     private ValueConverter converter;
 
     /**
+     * Converters from arbitrary classes implementing GeoAPI interfaces to Apache SIS implementations
+     * providing JAXB annotations, or null or an empty array if none. This is used at marshalling
time.
+     *
+     * @see #getRootAdapters()
+     */
+    private TypeRegistration[] rootAdapters;
+
+    /**
      * The object to inform about warnings, or {@code null} if none.
      */
     private WarningListener<?> warningListener;
@@ -199,7 +208,7 @@ abstract class Pooled {
      * @throws JAXBException if an error occurred while setting a property.
      */
     final void initialize(final Pooled template) throws JAXBException {
-        reset(template); // Set the SIS properties first. JAXB properties are set below.
+        reset(template);     // Set the SIS properties first. JAXB properties are set below.
         for (final Map.Entry<Object,Object> entry : template.initialProperties.entrySet())
{
             setStandardProperty((String) entry.getKey(), entry.getValue());
         }
@@ -226,6 +235,7 @@ abstract class Pooled {
         versionGML       = template.versionGML;
         resolver         = template.resolver;
         converter        = template.converter;
+        rootAdapters     = template.rootAdapters;
         warningListener  = template.warningListener;
         resetTime        = System.nanoTime();
         if (this instanceof Marshaller) {
@@ -397,6 +407,11 @@ abstract class Pooled {
                     }
                     return;
                 }
+                case TypeRegistration.ROOT_ADAPTERS: {
+                    rootAdapters = (TypeRegistration[]) value;
+                    // No clone for now because ROOT_ADAPTERS is not yet a public API.
+                    return;
+                }
             }
         } catch (ClassCastException | IllformedLocaleException e) {
             throw new PropertyException(Errors.format(
@@ -445,6 +460,7 @@ abstract class Pooled {
                     default: return null;
                 }
             }
+            case TypeRegistration.ROOT_ADAPTERS: return (rootAdapters != null) ? rootAdapters.clone()
: null;
             default: {
                 return getStandardProperty(convertPropertyKey(name));
             }
@@ -493,6 +509,18 @@ abstract class Pooled {
     public abstract <A extends XmlAdapter> A getAdapter(final Class<A> type);
 
     /**
+     * Returns the adapters to apply on the root object to marshal, or {@code null} or an
empty array if none.
+     * This is used for converting from arbitrary implementations of GeoAPI interfaces to
Apache SIS implementations
+     * providing JAXB annotations.
+     *
+     * @return a direct reference to the internal array of converters - do not modify.
+     */
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
+    final TypeRegistration[] getRootAdapters() {
+        return rootAdapters;
+    }
+
+    /**
      * A method which is common to both {@code Marshaller} and {@code Unmarshaller}.
      * It saves the initial state if it was not already done, but subclasses will
      * need to complete the work.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledMarshaller.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -36,6 +36,7 @@ import javax.xml.validation.Schema;
 import org.xml.sax.ContentHandler;
 import org.w3c.dom.Node;
 import org.apache.sis.internal.jaxb.Context;
+import org.apache.sis.internal.jaxb.TypeRegistration;
 
 
 /**
@@ -53,7 +54,7 @@ import org.apache.sis.internal.jaxb.Cont
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.8
  * @module
  */
 final class PooledMarshaller extends Pooled implements Marshaller {
@@ -90,7 +91,7 @@ final class PooledMarshaller extends Poo
         if (key instanceof String) {
             final String k = (String) key;
             if (value == null && (k.endsWith(".xmlHeaders") || k.equals(JAXB_SCHEMA_LOCATION)))
{
-                value = ""; // Null value doesn't seem to be accepted for those properties.
+                value = "";      // Null value does not seem to be accepted for those properties.
             }
             marshaller.setProperty(k, value);
         } else if (key == AttachmentMarshaller.class) {
@@ -114,14 +115,30 @@ final class PooledMarshaller extends Poo
     }
 
     /**
+     * Converts the given arbitrary object to an implementation having JAXB annotations.
+     * If the given object is not recognized or is already an instance of the expected class,
+     * then it is returned unchanged.
+     */
+    private Object toImplementation(final Object value) throws JAXBException {
+        final TypeRegistration[] converters = getRootAdapters();
+        if (converters != null) {
+            for (final TypeRegistration t : converters) {
+                final Object c = t.toImplementation(value);
+                if (c != null) return c;
+            }
+        }
+        return value;
+    }
+
+    /**
      * Marshals to the given output with on-the-fly substitution of namespaces.
      * This method is invoked only when the user asked to marshal to a different GML version
      * than the one supported natively by SIS, i.e. when {@link #getFilterVersion()} returns
      * a non-null value.
      *
-     * @param object  the object to marshall.
-     * @param output  the writer created by SIS (<b>not</b> the writer given
by the user).
-     * @param version Identify the namespace substitutions to perform.
+     * @param object   the object to marshall.
+     * @param output   the writer created by SIS (<b>not</b> the writer given
by the user).
+     * @param version  identifies the namespace substitutions to perform.
      */
     private void marshal(final Object object, XMLStreamWriter output, final FilterVersion
version)
             throws XMLStreamException, JAXBException
@@ -129,7 +146,7 @@ final class PooledMarshaller extends Poo
         output = new FilteredStreamWriter(output, version);
         final Context context = begin();
         try {
-            marshaller.marshal(object, output);
+            marshaller.marshal(toImplementation(object), output);
         } finally {
             context.finish();
         }
@@ -150,7 +167,7 @@ final class PooledMarshaller extends Poo
             // Marshalling to the default GML version.
             final Context context = begin();
             try {
-                marshaller.marshal(object, output);
+                marshaller.marshal(toImplementation(object), output);
             } finally {
                 context.finish();
             }
@@ -171,7 +188,7 @@ final class PooledMarshaller extends Poo
             // Marshalling to the default GML version.
             final Context context = begin();
             try {
-                marshaller.marshal(object, output);
+                marshaller.marshal(toImplementation(object), output);
             } finally {
                 context.finish();
             }
@@ -194,7 +211,7 @@ final class PooledMarshaller extends Poo
             // Marshalling to the default GML version.
             final Context context = begin();
             try {
-                marshaller.marshal(object, output);
+                marshaller.marshal(toImplementation(object), output);
             } finally {
                 context.finish();
             }
@@ -215,7 +232,7 @@ final class PooledMarshaller extends Poo
             // Marshalling to the default GML version.
             final Context context = begin();
             try {
-                marshaller.marshal(object, output);
+                marshaller.marshal(toImplementation(object), output);
             } finally {
                 context.finish();
             }
@@ -236,7 +253,7 @@ final class PooledMarshaller extends Poo
             // Marshalling to the default GML version.
             final Context context = begin();
             try {
-                marshaller.marshal(object, output);
+                marshaller.marshal(toImplementation(object), output);
             } finally {
                 context.finish();
             }
@@ -257,7 +274,7 @@ final class PooledMarshaller extends Poo
             // Marshalling to the default GML version.
             final Context context = begin();
             try {
-                marshaller.marshal(object, output);
+                marshaller.marshal(toImplementation(object), output);
             } finally {
                 context.finish();
             }
@@ -275,7 +292,7 @@ final class PooledMarshaller extends Poo
         }
         final Context context = begin();
         try {
-            marshaller.marshal(object, output);
+            marshaller.marshal(toImplementation(object), output);
         } finally {
             context.finish();
         }
@@ -295,7 +312,7 @@ final class PooledMarshaller extends Poo
             // Marshalling to the default GML version.
             final Context context = begin();
             try {
-                marshaller.marshal(object, output);
+                marshaller.marshal(toImplementation(object), output);
             } finally {
                 context.finish();
             }
@@ -314,7 +331,7 @@ final class PooledMarshaller extends Poo
         } else {
             final Context context = begin();
             try {
-                return marshaller.getNode(object);
+                return marshaller.getNode(toImplementation(object));
             } finally {
                 context.finish();
             }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/PooledTemplate.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -40,9 +40,9 @@ final class PooledTemplate extends Poole
      * Creates a new template.
      *
      * @param properties  the properties to be given to JAXB (un)marshallers, or {@code null}
if none.
-     * @param internal {@code true} if the JAXB implementation is the one bundled in JDK
6,
-     *        or {@code false} if this is the external implementation provided as a JAR file
-     *        in the endorsed directory.
+     * @param internal    {@code true} if the JAXB implementation is the one bundled in JDK
6, or
+     *                    {@code false} if this is the external implementation provided as
a JAR file
+     *                    in the endorsed directory.
      */
     PooledTemplate(final Map<String,?> properties, final boolean internal) throws PropertyException
{
         super(internal);
@@ -83,7 +83,7 @@ final class PooledTemplate extends Poole
      * <p>Current implementation expects values of type {@code String}, but this may
be generalized
      * in a future SIS version if there is a need for that.</p>
      *
-     * @param  name  the name of the property to remove.
+     * @param  name          the name of the property to remove.
      * @param  defaultValue  the default value to return if the given property is not defined
in the map.
      * @return the old value of that property, or {@code defaultValue} if the given property
was not defined.
      * @throws PropertyException if the given property is not of the expected type.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java [UTF-8] Mon
Jan 23 10:55:29 2017
@@ -308,8 +308,7 @@ public final class XML extends Static {
      * this field is initially null, then created by {@link #getPool()} when first needed.
      * Once created the field value usually doesn't change. However the field may be reset
      * to {@code null} in an OSGi context when modules are loaded or unloaded, because the
-     * set of classes returned by {@link TypeRegistration#defaultClassesToBeBound()} may
-     * have changed.
+     * set of classes returned by {@link TypeRegistration#load(boolean)} may have changed.
      *
      * @see #getPool()
      */

Modified: sis/branches/JDK8/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java
[UTF-8] (original)
+++ sis/branches/JDK8/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -26,7 +26,7 @@ import org.apache.sis.internal.jaxb.Type
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.8
  * @module
  */
 public final class ProfileTypes extends TypeRegistration {
@@ -34,7 +34,7 @@ public final class ProfileTypes extends
      * Adds to the given collection the metadata types that should be given to the initial
JAXB context.
      */
     @Override
-    public void getTypes(final Collection<Class<?>> addTo) {
+    protected void getTypes(final Collection<Class<?>> addTo) {
         addTo.add(DataIdentification.class);
         addTo.add(DirectReferenceSystem.class);
         addTo.add(IndirectReferenceSystem.class);

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java?rev=1779902&r1=1779901&r2=1779902&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java
[UTF-8] Mon Jan 23 10:55:29 2017
@@ -38,6 +38,7 @@ import org.opengis.metadata.identificati
 import org.opengis.metadata.identification.Identification;
 import org.opengis.metadata.content.ContentInformation;
 import org.opengis.metadata.distribution.Format;
+import org.opengis.referencing.ReferenceSystem;
 import org.opengis.util.InternationalString;
 
 import org.apache.sis.io.TableAppender;
@@ -46,6 +47,7 @@ import org.apache.sis.internal.util.Unmo
 import org.apache.sis.metadata.iso.citation.DefaultCitationDate;
 import org.apache.sis.metadata.iso.identification.DefaultKeywords;
 import org.apache.sis.metadata.iso.extent.Extents;
+import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.util.iso.Types;
 
@@ -349,6 +351,17 @@ public final class Metadata extends Simp
     }
 
     /**
+     * Description of the spatial and temporal reference systems used in the dataset.
+     * This is fixed to WGS 84 in GPX files. We use (latitude, longitude) axis order.
+     *
+     * @return WGS 84 (EPSG:4326).
+     */
+    @Override
+    public Collection<ReferenceSystem> getReferenceSystemInfo() {
+        return Collections.singletonList(CommonCRS.WGS84.geographic());
+    }
+
+    /**
      * ISO 19115 metadata property determined by the {@link #time} field.
      * This is part of the information returned by {@link #getCitation()}.
      *



Mime
View raw message