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()}.
*
|