This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new b81a8f5 Introduce a new syntax in "RenameOnImport.lst" file for
declaring that a class inherit the properties of another class. It make the
file shorter and reduce the amount of hack with namespaces. But the main intent
is to make easier to extend with profile. This work allow us to fix
https://issues.apache.org/jira/browse/SIS-404
b81a8f5 is described below
commit b81a8f5a94799bac67588de02e502a00e924f111
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Tue Oct 9 19:33:25 2018 +0200
Introduce a new syntax in "RenameOnImport.lst" file for declaring that a
class inherit the properties of another class.
It make the file shorter and reduce the amount of hack with namespaces. But
the main intent is to make easier to extend with profile.
This work allow us to fix https://issues.apache.org/jira/browse/SIS-404
---
.../apache/sis/internal/jaxb/TypeRegistration.java | 133 +++++---
.../sis/internal/metadata/MetadataTypes.java | 13 +-
.../java/org/apache/sis/xml/MarshallerPool.java | 2 +-
.../src/main/java/org/apache/sis/xml/Pooled.java | 10 +-
.../java/org/apache/sis/xml/PooledMarshaller.java | 10 +-
.../main/java/org/apache/sis/xml/Transformer.java | 159 +++++----
.../org/apache/sis/xml/TransformingReader.java | 15 +-
.../org/apache/sis/xml/TransformingWriter.java | 8 +-
.../src/main/java/org/apache/sis/xml/readme.html | 74 +++++
.../org/apache/sis/xml/RenameOnExport.lst | 15 +-
.../org/apache/sis/xml/RenameOnImport.lst | 354 +++------------------
.../org/apache/sis/xml/RenameListGenerator.java | 19 +-
.../sis/internal/referencing/ReferencingTypes.java | 16 +-
.../sis/internal/system/DelayedExecutor.java | 2 +-
.../sis/internal/system/DelayedRunnable.java | 14 +-
ide-project/NetBeans/build.xml | 3 +
.../sis/internal/profile/fra/ProfileTypes.java | 14 +-
.../sis/internal/profile/fra/package-info.java | 2 +-
.../sis/internal/profile/fra/RenameOnImport.lst | 10 +
.../profile/fra/DataIdentificationTest.java | 2 -
20 files changed, 414 insertions(+), 461 deletions(-)
diff --git
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
index a0c0624..e3a4bb3 100644
---
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
+++
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
@@ -16,11 +16,15 @@
*/
package org.apache.sis.internal.jaxb;
+import java.util.Set;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.ServiceLoader;
+import java.util.concurrent.TimeUnit;
+import java.util.function.UnaryOperator;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import javax.xml.bind.JAXBContext;
@@ -28,6 +32,8 @@ import javax.xml.bind.JAXBException;
import org.apache.sis.internal.system.Modules;
import org.apache.sis.internal.system.SystemListener;
import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.internal.system.DelayedExecutor;
+import org.apache.sis.internal.system.DelayedRunnable;
/**
@@ -42,7 +48,7 @@ import org.apache.sis.internal.system.DefaultFactories;
* }
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
*
* @see org.apache.sis.xml.MarshallerPool
*
@@ -52,9 +58,9 @@ import org.apache.sis.internal.system.DefaultFactories;
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.
+ * before marshalling. Conversions are applied by {@link UnaryOperator}
instances.
*
- * @see #addDefaultRootAdapters(Map)
+ * @see #getPrivateInfo(Map)
*/
public static final String ROOT_ADAPTERS =
"org.apache.sis.xml.rootAdapters";
@@ -66,12 +72,20 @@ public abstract class TypeRegistration {
private static Reference<JAXBContext> context;
/**
- * The {@link TypeRegistration} instances found on the classpath for which
the
- * {@link #toImplementation(Object)} method has been overridden.
+ * Converters to apply before to marshal an object, or an empty array if
none.
+ * This is {@code null} if not yet initialized or if classpath changed.
*
- * @see #addDefaultRootAdapters(Map)
+ * @see #getPrivateInfo(Map)
*/
- private static TypeRegistration[] converters;
+ private static UnaryOperator<Object>[] converters;
+
+ /**
+ * The registrations, cached only a few seconds. We do not need to keep
them a long time
+ * because {@link TypeRegistration} is used only for initializing some
classes or fields.
+ *
+ * @see #services()
+ */
+ private static ServiceLoader<TypeRegistration> services;
/**
* Forces reloading of JAXB context and converters if the classpath
changes.
@@ -82,6 +96,7 @@ public abstract class TypeRegistration {
synchronized (TypeRegistration.class) {
context = null;
converters = null;
+ services = null;
}
}
});
@@ -97,75 +112,91 @@ public abstract class TypeRegistration {
* 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.
+ * then the {@link #beforeMarshal()} method should be overridden.
*
* @param addTo the collection in which to add new types.
*/
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.
+ * If some objects need to be converted before marshalling, the converter
for performing those conversions.
+ * The converter {@code apply(Object)} method may return {@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.
+ * Implementations will typically perform an {@code instanceof} check,
then invoke one
+ * of the {@code castOrCopy(…)} static methods defined in various Apache
SIS classes.
*
- * @return whether the module can also marshal arbitrary implementation of
some interfaces.
+ * @return converter for the value to marshal, or {@code null} if there is
no value to convert.
*
* @since 0.8
*/
- protected boolean canMarshalInterfaces() {
- return false;
+ protected UnaryOperator<Object> beforeMarshal() {
+ return null;
}
/**
- * 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>
+ * Returns {@code true} if {@code "RenameOnImport.lst"} and/or {@code
"RenameOnExport.lst"} files are provided.
+ * If {@code true}, then those files shall be located in the same
directory than this {@code TypeRegistration}
+ * subclass.
*
- * <p>This method is invoked only if {@link #canMarshalInterfaces()}
returns {@code true}.</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.
+ * @param export {@code true} for {@code "RenameOnImport.lst"}, {@code
false} for {@code "RenameOnImport.lst"}.
+ * @return whether {@code "RenameOnImport.lst"} and/or {@code
"RenameOnExport.lst"} files are provided.
+ */
+ protected boolean hasRenameFile(boolean export) {
+ return false;
+ }
+
+ /**
+ * Adds in the given set the classes to use for loading {@code
"RenameOnImport.lst"} and/or {@code "RenameOnExport.lst"} files.
+ * The given set should preserve insertion order, since the order in which
files are loaded may matter.
*
- * @since 0.8
+ * @param export {@code true} for {@code "RenameOnImport.lst"}, {@code
false} for {@code "RenameOnImport.lst"}.
+ * @param addTo where to add the classes to use for loading the
resource files.
*/
- public Object toImplementation(final Object value) throws JAXBException {
- return null;
+ public static synchronized void getRenameFileLoader(final boolean export,
final Set<Class<?>> addTo) {
+ for (final TypeRegistration t : services()) {
+ if (t.hasRenameFile(export)) {
+ addTo.add(t.getClass());
+ }
+ }
+ }
+
+ /**
+ * Returns the {@code TypeRegistration} instances.
+ * Must be invoked in a synchronized block.
+ */
+ private static ServiceLoader<TypeRegistration> services() {
+ ServiceLoader<TypeRegistration> s = services;
+ if (s == null) {
+ services = s =
DefaultFactories.createServiceLoader(TypeRegistration.class);
+ DelayedExecutor.schedule(new DelayedRunnable(1, TimeUnit.MINUTES) {
+ @Override public void run() {services = null;}
+ });
+ }
+ return s;
}
/**
* 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}.
+ * This method does nothing if this class already has all required
information.
+ *
+ * <p>The list of converters is cached (that result is stored in {@link
#converters}) while the list
+ * of root classes in JAXB context is not cached. So the information about
whether this method needs
+ * to fetch the list of root classes or not must be specified by the
{@code getTypes} argument.</p>
*
* @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}.
*/
+ @SuppressWarnings({"unchecked", "rawtypes"})
private static Class<?>[] load(final boolean getTypes) {
- /*
- * Implementation note: do not keep the ServiceLoader in static field
because:
- *
- * 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<>();
- 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()]);
- }
+ final ArrayList<Class<?>> types = new ArrayList<>();
+ final ArrayList<UnaryOperator<Object>> toImpl = new ArrayList<>();
+ for (final TypeRegistration t : services()) {
+ if (getTypes) t.getTypes(types);
+ final UnaryOperator<Object> c = t.beforeMarshal();
+ if (c != null) toImpl.add(c);
}
+ converters = toImpl.toArray(new UnaryOperator[toImpl.size()]);
return types.toArray(new Class<?>[types.size()]);
}
@@ -205,11 +236,11 @@ public abstract class TypeRegistration {
*
* @since 0.8
*/
- public static Map<String,?> addDefaultRootAdapters(final Map<String,?>
properties) {
+ public static Map<String,?> getPrivateInfo(final Map<String,?> properties)
{
if (properties != null && properties.containsKey(ROOT_ADAPTERS)) {
return properties;
}
- TypeRegistration[] c;
+ UnaryOperator<Object>[] c;
synchronized (TypeRegistration.class) {
c = converters;
if (c == null) {
diff --git
a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataTypes.java
b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataTypes.java
index baec5da..67a212d 100644
---
a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataTypes.java
+++
b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/MetadataTypes.java
@@ -17,6 +17,7 @@
package org.apache.sis.internal.metadata;
import java.util.Collection;
+import java.util.function.UnaryOperator;
import org.opengis.metadata.Metadata;
import org.opengis.metadata.content.Band;
import org.opengis.metadata.content.ImageDescription;
@@ -47,7 +48,7 @@ import org.opengis.metadata.spatial.Georeferenceable;
* @since 0.3
* @module
*/
-public final class MetadataTypes extends TypeRegistration {
+public final class MetadataTypes extends TypeRegistration implements
UnaryOperator<Object> {
/**
* Adds to the given collection the metadata types that should be given to
the initial JAXB context.
*/
@@ -58,13 +59,13 @@ public final class MetadataTypes extends TypeRegistration {
}
/**
- * Notifies that the {@code sis-metadata} module can marshal arbitrary
implementations of some metadata interfaces.
+ * Returns the converter to apply before marshalling objects.
*
- * @return {@code true}.
+ * @return {@code this}.
*/
@Override
- protected boolean canMarshalInterfaces() {
- return true;
+ protected UnaryOperator<Object> beforeMarshal() {
+ return this;
}
/**
@@ -78,7 +79,7 @@ public final class MetadataTypes extends TypeRegistration {
* @return the given value as a type that can be marshalled, or {@code
null}.
*/
@Override
- public Object toImplementation(final Object value) {
+ public Object apply(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
diff --git
a/core/sis-metadata/src/main/java/org/apache/sis/xml/MarshallerPool.java
b/core/sis-metadata/src/main/java/org/apache/sis/xml/MarshallerPool.java
index 6d3e9ae..a35a90c 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/MarshallerPool.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/MarshallerPool.java
@@ -165,7 +165,7 @@ public class MarshallerPool {
* 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));
+ this(TypeRegistration.getSharedContext(),
TypeRegistration.getPrivateInfo(properties));
}
/**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/xml/Pooled.java
b/core/sis-metadata/src/main/java/org/apache/sis/xml/Pooled.java
index 3bf4389..e468a6b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/Pooled.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/Pooled.java
@@ -23,6 +23,7 @@ import java.util.ConcurrentModificationException;
import java.util.IllformedLocaleException;
import java.util.Locale;
import java.util.TimeZone;
+import java.util.function.UnaryOperator;
import javax.xml.validation.Schema;
import javax.xml.bind.Marshaller;
import javax.xml.bind.JAXBException;
@@ -146,7 +147,7 @@ abstract class Pooled {
*
* @see #getRootAdapters()
*/
- private TypeRegistration[] rootAdapters;
+ private UnaryOperator<Object>[] rootAdapters;
/**
* The object to inform about warnings, or {@code null} if none.
@@ -381,8 +382,9 @@ abstract class Pooled {
return;
}
case TypeRegistration.ROOT_ADAPTERS: {
- rootAdapters = (TypeRegistration[]) value;
- // No clone for now because ROOT_ADAPTERS is not yet a
public API.
+ @SuppressWarnings("unchecked")
+ UnaryOperator<Object>[] c = (UnaryOperator<Object>[])
value;
+ rootAdapters = c; // No clone for now because
ROOT_ADAPTERS is not yet a public API.
return;
}
}
@@ -487,7 +489,7 @@ abstract class Pooled {
* @return a direct reference to the internal array of converters - do not
modify.
*/
@SuppressWarnings("ReturnOfCollectionOrArrayField")
- final TypeRegistration[] getRootAdapters() {
+ final UnaryOperator<Object>[] getRootAdapters() {
return rootAdapters;
}
diff --git
a/core/sis-metadata/src/main/java/org/apache/sis/xml/PooledMarshaller.java
b/core/sis-metadata/src/main/java/org/apache/sis/xml/PooledMarshaller.java
index 55027e4..b212908 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/PooledMarshaller.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/PooledMarshaller.java
@@ -22,6 +22,7 @@ import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
+import java.util.function.UnaryOperator;
import javax.xml.bind.Marshaller;
import javax.xml.bind.JAXBException;
import javax.xml.bind.PropertyException;
@@ -36,7 +37,6 @@ 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;
import org.apache.sis.internal.jaxb.UseLegacyMetadata;
@@ -138,12 +138,12 @@ final class PooledMarshaller extends Pooled implements
Marshaller {
* 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 {
+ private Object toImplementation(final Object value) {
specificBitMasks =
value.getClass().isAnnotationPresent(UseLegacyMetadata.class) ?
Context.LEGACY_METADATA : 0;
- final TypeRegistration[] converters = getRootAdapters();
+ final UnaryOperator<Object>[] converters = getRootAdapters();
if (converters != null) {
- for (final TypeRegistration t : converters) {
- final Object c = t.toImplementation(value);
+ for (final UnaryOperator<Object> t : converters) {
+ final Object c = t.apply(value);
if (c != null) return c;
}
}
diff --git
a/core/sis-metadata/src/main/java/org/apache/sis/xml/Transformer.java
b/core/sis-metadata/src/main/java/org/apache/sis/xml/Transformer.java
index 705ccdb..0c49150 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/Transformer.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/Transformer.java
@@ -18,14 +18,18 @@ package org.apache.sis.xml;
import java.util.Map;
import java.util.HashMap;
+import java.util.Set;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.NoSuchElementException;
import java.util.InvalidPropertiesFormatException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
+import java.util.function.Function;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
@@ -34,6 +38,7 @@ import javax.xml.stream.events.Namespace;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.internal.jaxb.TypeRegistration;
/**
@@ -98,7 +103,15 @@ abstract class Transformer {
private static final char RENAME_SEPARATOR = '/';
/**
- * A flag after type name in files loaded by {@link #load(String, int)},
meaning that the type itself
+ * Character used for separating a class name from the parent class name.
When the {@code Child : Parent} syntax
+ * is used, the child inherits all properties defined in the parent. The
parent class must be defined before the
+ * child class (no forward reference). We do not store the relationship
between the two classes, so it is not
+ * necessary to extend a parent that define no property.
+ */
+ private static final char EXTENDS = ':';
+
+ /**
+ * A flag after type name in files loaded by {@link #load(boolean, String,
int)}, meaning that the type itself
* is in a different namespace than the properties listed below the type.
For example in the following:
*
* {@preformat text
@@ -110,8 +123,9 @@ abstract class Transformer {
*
* {@code SV_ServiceIdentification} type is defined in the {@code
"http://standards.iso.org/iso/19115/-3/srv/2.0"}
* namespace, but the {@code citation} and {@code abstract} properties
inherited from {@code Identification} are
- * defined in the {@code http://standards.iso.org/iso/19115/-3/mri/1.0}
namespace. If the {@value} flag is not
- * present, then the type is assumed in the same namespace than the
properties (this is the most common case).
+ * defined in the {@code http://standards.iso.org/iso/19115/-3/mri/1.0}
namespace (note: using {@link #EXTENDS}
+ * is a better way to achieve the same result for this particular
example). If the {@value} flag is not present,
+ * then the type is assumed in the same namespace than the properties
(this is the most common case).
*/
static final char NO_NAMESPACE = '!';
@@ -184,8 +198,8 @@ abstract class Transformer {
/**
* Returns {@code true} if the given string is a namespace URI, or {@code
false} if it is a property name.
* This method implements a very fast check based on the presence of
{@code ':'} in {@code "http://foo.bar"}.
- * It assumes that all namespaces declared in files loaded by {@link
#load(String, int)} use the {@code "http"}
- * protocol and no property name use the {@code ':'} character.
+ * It assumes that all namespaces declared in files loaded by {@link
#load(boolean, String, int)} use the
+ * {@code "http"} protocol and no property name use the {@code ':'}
character.
*/
static boolean isNamespace(final String candidate) {
return (candidate.length() > 4) && (candidate.charAt(4) == ':');
@@ -220,63 +234,98 @@ abstract class Transformer {
* </ul></li>
* </ul>
*
+ * @param export {@code true} for {@code "RenameOnImport.lst"}, {@code
false} for {@code "RenameOnImport.lst"}.
* @param filename name of the file to load.
* @param capacity initial hash map capacity. This is only a hint.
*/
- static Map<String, Map<String,String>> load(final String filename, final
int capacity) {
+ static Map<String, Map<String,String>> load(final boolean export, final
String filename, final int capacity) {
final Map<String, Map<String,String>> m = new HashMap<>(capacity);
- try (LineNumberReader in = new LineNumberReader(new InputStreamReader(
- TransformingReader.class.getResourceAsStream(filename),
"UTF-8")))
- {
- Map<String,String> attributes = null; // All
attributes for a given type.
- String namespace = null; // Value to
store in 'attributes' map.
- String line;
- while ((line = in.readLine()) != null) {
- final int length = line.length();
- final int start = CharSequences.skipLeadingWhitespaces(line,
0, length);
- if (start < length && line.charAt(start) != '#') {
- String element = line.substring(start).trim();
- switch (start) {
- case 0: {
// New namespace URI.
- if (!isNamespace(element)) break;
// Report illegal format.
- namespace = element.intern();
- attributes = null;
- continue;
- }
- case 1: {
// New type in above namespace URI.
- if (namespace == null) break;
// Report illegal format.
- final int s = element.indexOf(NO_NAMESPACE);
- if (s >= 0) {
- element = element.substring(0, s).trim();
- }
- element = element.intern();
- attributes = m.computeIfAbsent(element, (k) -> new
HashMap<>());
- if (s < 0) {
- // Record namespace for this type only if '!'
is not present.
- if (attributes.put(element, namespace) !=
null) break;
+ final Set<Class<?>> renameLoaders = new LinkedHashSet<>(8);
+ renameLoaders.add(Transformer.class);
+ TypeRegistration.getRenameFileLoader(export, renameLoaders);
+ for (final Class<?> loader : renameLoaders) {
+ try (LineNumberReader in = new LineNumberReader(new
InputStreamReader(loader.getResourceAsStream(filename), "UTF-8"))) {
+ Map<String,String> attributes = null; // All
attributes for a given type.
+ String namespace = null; // Value
to store in 'attributes' map.
+ String line;
+ while ((line = in.readLine()) != null) {
+ final int length = line.length();
+ final int start =
CharSequences.skipLeadingWhitespaces(line, 0, length);
+ if (start < length && line.charAt(start) != '#') {
+ String element = line.substring(start).trim();
+ switch (start) {
+ /*
+ * Begin a new namespace. Must be before any class
or property.
+ */
+ case 0: {
// New namespace URI.
+ if (!isNamespace(element)) break;
// Report illegal format.
+ namespace = element.intern();
+ attributes = null;
+ continue;
}
- continue;
- }
- case 2: {
// New attribute in above type.
- if (attributes == null || namespace == null)
break; // Report illegal format.
- final int s = element.indexOf(RENAME_SEPARATOR);
- if (s >= 0) {
- final String old = element.substring(0,
s).trim().intern();
- element =
element.substring(s+1).trim().intern();
- if (attributes.put(old, element) != null)
break; // Report an error if duplicated values.
- } else {
+ /*
+ * Add a class into the above-defined namespace.
+ * The class may inherit the properties of another
class.
+ * Inherited properties may be in a different
namespace than the new class.
+ */
+ case 1: {
// New type in above namespace URI.
+ if (namespace == null) break;
// Report illegal format.
+ final int noNS = element.indexOf(NO_NAMESPACE);
+ if (noNS >= 0) {
+ element =
CharSequences.trimWhitespaces(element, 0, noNS).toString();
+ }
+ final Function<String, Map<String,String>>
init;
+ final int s = element.indexOf(EXTENDS);
+ if (s >= 0) {
+ final String parent;
+ parent =
CharSequences.trimWhitespaces(element, s+1, element.length()).toString();
+ element =
CharSequences.trimWhitespaces(element, 0, s).toString();
+ init = (k) -> {
+ Map<String,String> properties =
m.get(parent);
+ if (properties != null) {
+ properties = new
HashMap<>(properties);
+ properties.remove(parent);
+ return properties;
+ }
+ throw new
NoSuchElementException(parent);
+ };
+ } else {
+ init = (k) -> new HashMap<>();
+ }
element = element.intern();
+ attributes = m.computeIfAbsent(element, init);
+ if (noNS < 0) {
+ // Record namespace for this type only if
'!' is not present.
+ if (attributes.put(element, namespace) !=
null) break;
+ }
+ continue;
+ }
+ /*
+ * Add a property into the above-defined class.
+ * All properties are associated to above-defined
namespace.
+ * A property may have an alias (e.g.
"center/centre").
+ */
+ case 2: {
// New attribute in above type.
+ if (attributes == null || namespace == null)
break; // Report illegal format.
+ final int s =
element.indexOf(RENAME_SEPARATOR);
+ if (s >= 0) {
+ final String old = element.substring(0,
s).trim().intern();
+ element =
element.substring(s+1).trim().intern();
+ if (attributes.put(old, element) != null)
break; // Report an error if duplicated values.
+ } else {
+ element = element.intern();
+ }
+ if (attributes.put(element, namespace) !=
null) break; // Report an error if duplicated values.
+ continue;
}
- if (attributes.put(element, namespace) != null)
break; // Report an error if duplicated values.
- continue;
}
+ throw new
InvalidPropertiesFormatException(Errors.format( // See method javadoc.
+ Errors.Keys.ErrorInFileAtLine_2, filename,
in.getLineNumber()));
}
- throw new InvalidPropertiesFormatException(Errors.format(
// See method javadoc.
- Errors.Keys.ErrorInFileAtLine_2, filename,
in.getLineNumber()));
}
+ } catch (IOException e) {
+ throw new ExceptionInInitializerError(e);
}
- } catch (IOException e) {
- throw new ExceptionInInitializerError(e);
}
/*
* At this point we finished computing the map values. Many values are
maps with only 1 entry.
@@ -443,9 +492,9 @@ abstract class Transformer {
}
/**
- * Renames en element using the namespaces map give to the {@code open(…)}
and {@code close(…)} methods.
- * When unmarshalling, this imports a name read from the XML document to
the name to give to JAXB.
- * When marshalling, this exports a name used in JAXB annotation to the
name to use in XML document.
+ * Renames en element using the namespaces map given to the {@code
open(…)} and {@code close(…)} methods.
+ * When unmarshalling, this method converts a name read from the XML
document to the name to give to JAXB.
+ * When marshalling, this method converts a name used in JAXB annotation
to the name to use in XML document.
* The new namespace depends on both the old namespace and the element
name.
* The prefix is computed by {@link #prefixReplacement(String, String)}.
*
@@ -475,7 +524,7 @@ abstract class Transformer {
}
/**
- * Returns the map loaded by {@link #load(String, int)}.
+ * Returns the map loaded by {@link #load(boolean, String, int)}.
* This is a static field in the {@link TransformingReader} or {@link
TransformingWriter} subclass.
*
* @param namespace the namespace URI for which to get the substitution
map (never null).
diff --git
a/core/sis-metadata/src/main/java/org/apache/sis/xml/TransformingReader.java
b/core/sis-metadata/src/main/java/org/apache/sis/xml/TransformingReader.java
index 34a0a1f..0da5899 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/TransformingReader.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/TransformingReader.java
@@ -39,7 +39,7 @@ import static javax.xml.stream.XMLStreamConstants.*;
/**
* A XML reader replacing the namespaces found in XML documents by the
namespaces expected by SIS at unmarshalling time.
* This class forwards every method calls to the wrapped {@link
XMLEventReader}, but with some {@code namespaceURI}
- * modified before being transfered. This class uses a dictionary for
identifying the XML namespaces expected by JAXB
+ * modified before being transferred. This class uses a dictionary for
identifying the XML namespaces expected by JAXB
* implementation. This is needed when a single namespace in a legacy schema
has been splitted into many namespaces
* in the newer schema. This happen for example in the upgrade from ISO
19139:2007 to ISO 19115-3.
* In such cases, we need to check which attribute is being mapped in order to
determine the new namespace.
@@ -77,7 +77,7 @@ final class TransformingReader extends Transformer implements
XMLEventReader {
*
* This map is initialized only once and should not be modified after that
point.
*/
- private static final Map<String, Map<String,String>> NAMESPACES =
load(FILENAME, 250);
+ private static final Map<String, Map<String,String>> NAMESPACES =
load(false, FILENAME, 260);
/**
* Returns the namespace for the given ISO type, or {@code null} if
unknown.
@@ -280,11 +280,11 @@ final class TransformingReader extends Transformer
implements XMLEventReader {
}
/**
- * Returns the map loaded by {@link #load(String, int)} if the given
namespace is a known legacy namespace.
- * This method returns a non-empty map only for legacy namespaces for
which the {@value #FILENAME} file has
- * been designed. This is necessary for avoiding confusion with classes of
the same name defined in other
- * standards. For example the {@code Record} class name is used by other
standards like Catalog Service for
- * the Web (OGC CSW), and we don't want to replace the namespace of CSW
classes.
+ * Returns the map loaded by {@link #load(boolean, String, int)} if the
given namespace is a known legacy namespace.
+ * This method returns a non-empty map only for legacy namespaces for
which the {@value #FILENAME} file has been designed.
+ * This is necessary for avoiding confusion with classes of the same name
defined in other standards.
+ * For example the {@code Record} class name is used by other standards
like Catalog Service for the Web (OGC CSW),
+ * and we don't want to replace the namespace of CSW classes.
*
* @param namespace the namespace URI for which to get the substitution
map.
* @return the substitution map for the given namespace, or an empty map
if none.
@@ -294,6 +294,7 @@ final class TransformingReader extends Transformer
implements XMLEventReader {
final Map<String, Map<String,String>> renamingMap(final String namespace) {
if (!namespace.isEmpty()) {
switch (removeTrailingSlash(namespace)) {
+ case "http://www.cnig.gouv.fr/2005/fra": // TODO: move
to sis-french-profile module.
case LegacyNamespaces.GMI_ALIAS:
case LegacyNamespaces.GMI:
case LegacyNamespaces.GMD:
diff --git
a/core/sis-metadata/src/main/java/org/apache/sis/xml/TransformingWriter.java
b/core/sis-metadata/src/main/java/org/apache/sis/xml/TransformingWriter.java
index ca570d2..2984ed3 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/TransformingWriter.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/TransformingWriter.java
@@ -62,10 +62,10 @@ final class TransformingWriter extends Transformer
implements XMLEventWriter {
* Location of the file listing types and their properties contained in
legacy namespaces.
* This is used for mapping new ISO 19115-3:2016 namespaces to legacy ISO
19139:2007 ones,
* where the same {@code "http://standards.iso.org/iso/19115/-3/…"} URI is
used in places
- * where legacy schemas had two distinct URIs: {@code
"http://www.isotc211.org/2005/gmd"}
+ * where legacy schema had two distinct URIs: {@code
"http://www.isotc211.org/2005/gmd"}
* and {@code "http://standards.iso.org/iso/19115/-2/gmi/1.0"}.
*/
- static final String FILENAME = "RenameOnExport.lst";
+ private static final String FILENAME = "RenameOnExport.lst";
/**
* The mapping from (<var>type</var>, <var>attribute</var>) pairs to
legacy namespaces.
@@ -84,7 +84,7 @@ final class TransformingWriter extends Transformer implements
XMLEventWriter {
*
* This map is initialized only once and should not be modified after that
point.
*/
- private static final Map<String, Map<String,String>> NAMESPACES =
load(FILENAME, 60);
+ private static final Map<String, Map<String,String>> NAMESPACES =
load(true, FILENAME, 60);
/**
* Elements that appear in different order in ISO 19139:2007 (or other
legacy standards) compared
@@ -214,7 +214,7 @@ final class TransformingWriter extends Transformer
implements XMLEventWriter {
}
/**
- * Returns the map loaded by {@link #load(String, int)}.
+ * Returns the map loaded by {@link #load(boolean, String, int)}.
*
* @param namespace the namespace URI for which to get the substitution
map.
* @return the substitution map for the given namespace.
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/xml/readme.html
b/core/sis-metadata/src/main/java/org/apache/sis/xml/readme.html
new file mode 100644
index 0000000..f03b263
--- /dev/null
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/readme.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Syntax of Rename files</title>
+ <meta charset="UTF-8">
+ <style>
+ p {
+ text-align: justify;
+ }
+ pre {
+ border-left-style: solid;
+ border-left-color: darkgray;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>Syntax of <code>RenameOnImport</code>/<code>Export</code> files</h1>
+ <p>
+ <b>WARNING: the syntax documented in this page is not committed API and
may change in any future SIS version.</b>
+ </p>
+ <p>
+ This package provides two files in the
<code>resources/org/apache/sis/xml/</code> folder:
+ <code>RenameOnImport.lst</code> and <code>RenameOnExport.lst</code>.
+ Those files are used by <code>TransformingReader.java</code> and
<code>TransformingWriter.java</code> respectively
+ for converting XML namespaces between new specifications (ISO
19115-3:2016 and ISO 19115-4) and old specifications
+ (ISO 19139:2007 and ISO 19115-2:2009). The JAXB annotations in Apache
SIS use the newer specifications.
+ The <code>Rename*.lst</code> files are needed only when reading or
writing to older specifications.
+ Those files are used for performing the work of a lightweight XSLT
engine.
+ Both share the same syntax:
+ </p>
+ <ul>
+ <li>Lines with zero-space indentation are namespace URIs.</li>
+ <li>Lines with one-space indentation are XML type names.</li>
+ <li>Lines with two-spaces indentation are property names.</li>
+ <li>The "/" character in "<var>before</var>/<var>after</var>" means that
a property name needs to be changed.
+ <var>Before</var> is the name before the renaming process and
<var>after</var> is the name after the renaming process.</li>
+ <li>The ":" character in "<var>Parent</var> : <var>Child</var>" means
that a subclass inherits all properties from a parent class.
+ The <var>parent</var> must be defined before the <var>child</var>
(no forward references).
+ <li>The "!" character in "<var>Class</var> !<var>reason</var>" skips the
association of current namespace to that class
+ (but namespace will still be associated to the properties).
<var>Reason</var> is a free text.</li>
+ </ul>
+ <p>
+ For example the following snippet from <code>RenameOnImport.lst</code>
declares that the <code>Citation.title</code>,
+ <code>Citation.edition</code> and <code>Address.country</code>
properties are defined in the <b><code>cit</code></b> namespace,
+ while the <code>Extent.description</code> property is defined in the
<b><code>gex</code></b> namespace
+ and the <code>Georectified.centrePoint</code> property is defined in the
<b><code>msr</code></b> namespace.
+ Those information are required when reading a file encoded by the old
standards
+ because almost all properties where in the single <code>gmd</code>
namespace.
+ In general those information are used for converting only the
<em>namespaces</em>; the class and property names are unchanged.
+ But in the special case where the "<var>before</var>/<var>after</var>"
syntax is used, then class and/or property names are also changed.
+ For example in the following example,
<code>Georectified.centerPoint</code> (from the old standard)
+ is renamed as <code>Georectified.centrePoint</code> (new standard).
+ </p>
+ <blockquote><pre>http://standards.iso.org/iso/19115/-3/<b>cit</b>/1.0
+ CI_Citation
+ title
+ edition
+ CI_Address
+ country
+http://standards.iso.org/iso/19115/-3/<b>gex</b>/1.0
+ EX_Extent
+ description
+http://standards.iso.org/iso/19115/-3/<b>msr</b>/1.0
+ MI_Georectified
+ centerPoint/centrePoint</pre></blockquote>
+ <p>
+ Conversely, when writing a file, some additional renaming can be applied
<em>after</em> the namespaces have been renamed to <code>gmd</code>.
+ The following snippet from <code>RenameOnExport.lst</code> performs the
converse of the property renaming shown in previous example:
+ </p>
+ <blockquote><pre>http://www.isotc211.org/2005/gmd
+ MD_Georectified
+ centrePoint/centerPoint</pre></blockquote>
+ </body>
+</html>
diff --git
a/core/sis-metadata/src/main/resources/org/apache/sis/xml/RenameOnExport.lst
b/core/sis-metadata/src/main/resources/org/apache/sis/xml/RenameOnExport.lst
index 308e7ca..2ea16d3 100644
--- a/core/sis-metadata/src/main/resources/org/apache/sis/xml/RenameOnExport.lst
+++ b/core/sis-metadata/src/main/resources/org/apache/sis/xml/RenameOnExport.lst
@@ -1,15 +1,11 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements;
+# and to You under the Apache License, Version 2.0.
#
-# Elements to rename during exports.
-# Lines with zero-space indentation are namespace URIs.
-# Lines with one-space indentation are XML types.
-# Lines with two-spaces indentation are properties.
-# actual/exported means that a property needs to be renamed.
+# See readme.html is source code for the syntax of this file.
#
http://www.isotc211.org/2005/gmd
MD_Georectified
centrePoint/centerPoint
- MI_Georectified !other namespace
- centrePoint/centerPoint
DQ_QuantitativeResult
valueRecordType/valueType
http://www.isotc211.org/2005/srv
@@ -110,8 +106,7 @@ http://standards.iso.org/iso/19115/-2/gmi/1.0
detectedPolarisation
MI_CoverageDescription
rangeElementDescription
- MI_ImageDescription
- rangeElementDescription
+ MI_ImageDescription : MI_CoverageDescription
MI_RangeElementDescription
name
definition
@@ -155,7 +150,7 @@ http://standards.iso.org/iso/19115/-2/gmi/1.0
acquisitionInformation
MI_Georeferenceable
geolocationInformation
- MI_Georectified
+ MI_Georectified : MD_Georectified
checkPoint
MI_GCP
geographicCoordinates
diff --git
a/core/sis-metadata/src/main/resources/org/apache/sis/xml/RenameOnImport.lst
b/core/sis-metadata/src/main/resources/org/apache/sis/xml/RenameOnImport.lst
index d924669..5018d16 100644
--- a/core/sis-metadata/src/main/resources/org/apache/sis/xml/RenameOnImport.lst
+++ b/core/sis-metadata/src/main/resources/org/apache/sis/xml/RenameOnImport.lst
@@ -1,9 +1,7 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements;
+# and to You under the Apache License, Version 2.0.
#
-# Namespaces in which attribute are defined.
-# Lines with zero-space indentation are namespace URIs.
-# Lines with one-space indentation are XML types.
-# Lines with two-spaces indentation are properties.
-# old/new means that a property needs to be renamed.
+# See readme.html is source code for the syntax of this file.
#
http://standards.iso.org/iso/19115/-3/cit/1.0
AbstractCI_Party
@@ -39,9 +37,7 @@ http://standards.iso.org/iso/19115/-3/cit/1.0
date
dateType
CI_DateTypeCode
- CI_Individual
- contactInfo
- name
+ CI_Individual : AbstractCI_Party
positionName
CI_OnLineFunctionCode
CI_OnlineResource
@@ -52,20 +48,15 @@ http://standards.iso.org/iso/19115/-3/cit/1.0
name
protocol
protocolRequest
- CI_Organisation
- contactInfo
+ CI_Organisation : AbstractCI_Party
individual
logo
- name
CI_PresentationFormCode
CI_Responsibility
extent
party
role
- CI_ResponsibleParty !other namespace
- extent
- party
- role
+ CI_ResponsibleParty : CI_Responsibility !legacy
CI_RoleCode
CI_Series
issueIdentification
@@ -96,29 +87,25 @@ http://standards.iso.org/iso/19115/-3/gcx/1.0
http://standards.iso.org/iso/19115/-3/gex/1.0
AbstractEX_GeographicExtent
extentTypeCode
- EX_BoundingPolygon
- extentTypeCode
+ EX_BoundingPolygon : AbstractEX_GeographicExtent
polygon
EX_Extent
description
geographicElement
temporalElement
verticalElement
- EX_GeographicBoundingBox
+ EX_GeographicBoundingBox : AbstractEX_GeographicExtent
eastBoundLongitude
- extentTypeCode
northBoundLatitude
southBoundLatitude
westBoundLongitude
- EX_GeographicDescription
- extentTypeCode
+ EX_GeographicDescription : AbstractEX_GeographicExtent
geographicIdentifier
- EX_SpatialTemporalExtent
+ EX_TemporalExtent
extent
+ EX_SpatialTemporalExtent : EX_TemporalExtent
spatialExtent
verticalExtent
- EX_TemporalExtent
- extent
EX_VerticalExtent
maximumValue
minimumValue
@@ -267,31 +254,19 @@ http://standards.iso.org/iso/19115/-3/mco/1.0
releasability
responsibleParty
useLimitation
- MD_LegalConstraints
+ MD_LegalConstraints : MD_Constraints
accessConstraints
- constraintApplicationScope
- graphic
otherConstraints
- reference
- releasability
- responsibleParty
useConstraints
- useLimitation
MD_Releasability
addressee
disseminationConstraints
statement
MD_RestrictionCode
- MD_SecurityConstraints
+ MD_SecurityConstraints : MD_Constraints
classification
classificationSystem
- constraintApplicationScope
- graphic
handlingDescription
- reference
- releasability
- responsibleParty
- useLimitation
userNote
http://standards.iso.org/iso/19115/-3/mdb/1.0
MD_Metadata
@@ -322,31 +297,7 @@ http://standards.iso.org/iso/19115/-3/mdb/1.0
MD_MetadataScope
name
resourceScope
- MI_Metadata !other namespace
- acquisitionInformation
- alternativeMetadataReference
- applicationSchemaInfo
- contact
- contentInfo
- dataQualityInfo
- dateInfo
- defaultLocale
- distributionInfo
- identificationInfo
- metadataConstraints
- metadataExtensionInfo
- metadataIdentifier
- metadataLinkage
- metadataMaintenance
- metadataProfile
- metadataScope
- metadataStandard
- otherLocale
- parentMetadata
- portrayalCatalogueInfo
- referenceSystemInfo
- resourceLineage
- spatialRepresentationInfo
+ MI_Metadata : MD_Metadata !other namespace
http://standards.iso.org/iso/19115/-3/mdt/1.0
MX_DataFile
featureTypes
@@ -387,31 +338,6 @@ http://standards.iso.org/iso/19115/-3/mrc/1.0
MD_AttributeGroup
attribute
contentType
- MD_Band
- bandBoundaryDefinition
- bitsPerValue
- boundMax
- boundMin
- boundUnits
- description
- detectedPolarisation
- maxValue
- meanValue
- minValue
- name
- nominalSpatialResolution
- numberOfValues
- offset
- otherProperty
- otherPropertyType
- peakResponse
- scaleFactor
- sequenceIdentifier
- standardDeviation
- toneGradation
- transferFunctionType
- transmittedPolarisation
- units
MD_CoverageContentTypeCode
MD_CoverageDescription
attributeDescription
@@ -427,9 +353,7 @@ http://standards.iso.org/iso/19115/-3/mrc/1.0
MD_FeatureTypeInfo
featureInstanceCount
featureTypeName
- MD_ImageDescription
- attributeDescription
- attributeGroup
+ MD_ImageDescription : MD_CoverageDescription
cameraCalibrationInformationAvailability
cloudCoverPercentage
compressionGenerationQuantity
@@ -439,77 +363,40 @@ http://standards.iso.org/iso/19115/-3/mrc/1.0
imageQualityCode
imagingCondition
lensDistortionInformationAvailability
- processingLevelCode
radiometricCalibrationDataAvailability
- rangeElementDescription
triangulationIndicator
MD_ImagingConditionCode
MD_RangeDimension
description
name
sequenceIdentifier
- MD_SampleDimension
+ MD_SampleDimension : MD_RangeDimension
bitsPerValue
- description
maxValue
meanValue
minValue
- name
numberOfValues
offset
otherProperty
otherPropertyType
scaleFactor
- sequenceIdentifier
standardDeviation
units
- MI_Band
+ MD_Band : MD_SampleDimension
bandBoundaryDefinition
- bitsPerValue
boundMax
boundMin
boundUnits
- description
detectedPolarisation
- maxValue
- meanValue
- minValue
- name
nominalSpatialResolution
- numberOfValues
- offset
- otherProperty
- otherPropertyType
peakResponse
- scaleFactor
- sequenceIdentifier
- standardDeviation
toneGradation
transferFunctionType
transmittedPolarisation
- units
+ MI_Band : MD_Band
MI_BandDefinition
- MI_CoverageDescription
- attributeDescription
- attributeGroup
- processingLevelCode
- rangeElementDescription
- MI_ImageDescription
- attributeDescription
- attributeGroup
- cameraCalibrationInformationAvailability
- cloudCoverPercentage
- compressionGenerationQuantity
- filmDistortionInformationAvailability
- illuminationAzimuthAngle
- illuminationElevationAngle
- imageQualityCode
- imagingCondition
- lensDistortionInformationAvailability
- processingLevelCode
- radiometricCalibrationDataAvailability
- rangeElementDescription
- triangulationIndicator
+ MI_CoverageDescription : MD_CoverageDescription
+ MI_ImageDescription : MD_ImageDescription
MI_RangeElementDescription
definition
name
@@ -579,7 +466,7 @@ http://standards.iso.org/iso/19115/-3/mri/1.0
topicCategory
DS_AssociationTypeCode
DS_InitiativeTypeCode
- MD_AggregateInformation !other namespace
+ MD_AggregateInformation !legacy
metadataReference
name
MD_AssociatedResource
@@ -587,31 +474,11 @@ http://standards.iso.org/iso/19115/-3/mri/1.0
initiativeType
metadataReference
name
- MD_DataIdentification
- abstract
- additionalDocumentation
- associatedResource
- citation
- credit
+ MD_DataIdentification : AbstractMD_Identification
defaultLocale
- descriptiveKeywords
environmentDescription
- extent
- graphicOverview
otherLocale
- pointOfContact
- processingLevel
- purpose
- resourceConstraints
- resourceFormat
- resourceMaintenance
- resourceSpecificUsage
- spatialRepresentationType
- spatialResolution
- status
supplementalInformation
- temporalResolution
- topicCategory
MD_KeywordClass
className
conceptIdentifier
@@ -638,27 +505,6 @@ http://standards.iso.org/iso/19115/-3/mri/1.0
usageDateTime
userContactInfo
userDeterminedLimitations
- SV_ServiceIdentification !other namespace
- abstract
- additionalDocumentation
- associatedResource
- citation
- credit
- descriptiveKeywords
- extent
- graphicOverview
- pointOfContact
- processingLevel
- purpose
- resourceConstraints
- resourceFormat
- resourceMaintenance
- resourceSpecificUsage
- spatialRepresentationType
- spatialResolution
- status
- temporalResolution
- topicCategory
http://standards.iso.org/iso/19115/-3/mrl/1.0
LE_Algorithm
citation
@@ -740,71 +586,40 @@ http://standards.iso.org/iso/19115/-3/msr/1.0
MD_GeometricObjects
geometricObjectCount
geometricObjectType
- MD_Georectified
+ MD_GridSpatialRepresentation
axisDimensionProperties
cellGeometry
- centrePoint
+ numberOfDimensions
+ transformationParameterAvailability
+ MD_Georectified : MD_GridSpatialRepresentation
+ centerPoint/centrePoint
checkPoint
checkPointAvailability
checkPointDescription
cornerPoints
- numberOfDimensions
pointInPixel
transformationDimensionDescription
transformationDimensionMapping
- transformationParameterAvailability
- MD_Georeferenceable
- axisDimensionProperties
- cellGeometry
+ MD_Georeferenceable : MD_GridSpatialRepresentation
controlPointAvailability
geolocationInformation
georeferencedParameters
- numberOfDimensions
orientationParameterAvailability
orientationParameterDescription
parameterCitation
- transformationParameterAvailability
- MD_GridSpatialRepresentation
- axisDimensionProperties
- cellGeometry
- numberOfDimensions
- transformationParameterAvailability
MD_TopologyLevelCode
MD_VectorSpatialRepresentation
geometricObjects
topologyLevel
MI_GCP
accuracyReport
- MI_GCPCollection
+ MI_GCPCollection : AbstractMI_GeolocationInformation
collectionIdentification
collectionName
coordinateReferenceSystem
gcp
- qualityInfo
- MI_Georectified
- axisDimensionProperties
- cellGeometry
- centerPoint/centrePoint
- checkPoint
- checkPointAvailability
- checkPointDescription
- cornerPoints
- numberOfDimensions
- pointInPixel
- transformationDimensionDescription
- transformationDimensionMapping
- transformationParameterAvailability
- MI_Georeferenceable
- axisDimensionProperties
- cellGeometry
- controlPointAvailability
- geolocationInformation
- georeferencedParameters
- numberOfDimensions
- orientationParameterAvailability
- orientationParameterDescription
- parameterCitation
- transformationParameterAvailability
+ MI_Georectified : MD_Georectified
+ MI_Georeferenceable : MD_Georeferenceable
http://standards.iso.org/iso/19115/-3/srv/2.0
DCPList
SV_CoupledResource
@@ -831,7 +646,7 @@ http://standards.iso.org/iso/19115/-3/srv/2.0
repeatability
valueType
SV_ParameterDirection
- SV_ServiceIdentification
+ SV_ServiceIdentification : AbstractMD_Identification
accessProperties
containsChain
containsOperations
@@ -844,74 +659,22 @@ http://standards.iso.org/iso/19115/-3/srv/2.0
serviceType
serviceTypeVersion
http://standards.iso.org/iso/19157/-2/dqc/1.0
- AbstractDQ_Completeness !other namespace
- dateTime
AbstractDQ_Element !other namespace
dateTime
- AbstractDQ_LogicalConsistency !other namespace
- dateTime
- AbstractDQ_PositionalAccuracy !other namespace
- dateTime
- AbstractDQ_TemporalAccuracy !other namespace
- dateTime
- AbstractDQ_ThematicAccuracy !other namespace
- dateTime
- DQ_AbsoluteExternalPositionalAccuracy !other namespace
- dateTime
- DQ_AccuracyOfATimeMeasurement !other namespace
- dateTime
- DQ_CompletenessCommission !other namespace
- dateTime
- DQ_CompletenessOmission !other namespace
- dateTime
- DQ_ConceptualConsistency !other namespace
- dateTime
- DQ_DomainConsistency !other namespace
- dateTime
- DQ_FormatConsistency !other namespace
- dateTime
- DQ_GriddedDataPositionalAccuracy !other namespace
- dateTime
- DQ_NonQuantitativeAttributeAccuracy !other namespace
- dateTime
- DQ_QuantitativeAttributeAccuracy !other namespace
- dateTime
- DQ_RelativeInternalPositionalAccuracy !other namespace
- dateTime
- DQ_TemporalConsistency !other namespace
- dateTime
- DQ_TemporalValidity !other namespace
- dateTime
- DQ_ThematicClassificationCorrectness !other namespace
- dateTime
- DQ_TopologicalConsistency !other namespace
- dateTime
- QE_Usability !other namespace
- dateTime
http://standards.iso.org/iso/19157/-2/mdq/1.0
- AbstractDQ_Completeness
- result
AbstractDQ_Element
result
- AbstractDQ_LogicalConsistency
- result
- AbstractDQ_PositionalAccuracy
- result
+ AbstractDQ_Completeness : AbstractDQ_Element
+ AbstractDQ_LogicalConsistency : AbstractDQ_Element
+ AbstractDQ_PositionalAccuracy : AbstractDQ_Element
AbstractDQ_Result
- AbstractDQ_TemporalAccuracy !other namespace
- result
- AbstractDQ_ThematicAccuracy
- result
- DQ_AbsoluteExternalPositionalAccuracy
- result
- DQ_AccuracyOfATimeMeasurement
- result
- DQ_CompletenessCommission
- result
- DQ_CompletenessOmission
- result
- DQ_ConceptualConsistency
- result
+ AbstractDQ_TemporalAccuracy : AbstractDQ_Element !other namespace
+ AbstractDQ_ThematicAccuracy : AbstractDQ_Element
+ DQ_AbsoluteExternalPositionalAccuracy : AbstractDQ_PositionalAccuracy
+ DQ_AccuracyOfATimeMeasurement : AbstractDQ_TemporalAccuracy
+ DQ_CompletenessCommission : AbstractDQ_Completeness
+ DQ_CompletenessOmission : AbstractDQ_Completeness
+ DQ_ConceptualConsistency : AbstractDQ_LogicalConsistency
DQ_ConformanceResult
explanation
pass
@@ -919,39 +682,28 @@ http://standards.iso.org/iso/19157/-2/mdq/1.0
DQ_DataQuality
report
scope
- DQ_DomainConsistency
- result
+ DQ_DomainConsistency : AbstractDQ_LogicalConsistency
DQ_EvaluationMethodTypeCode
- DQ_FormatConsistency
- result
- DQ_GriddedDataPositionalAccuracy
- result
- DQ_NonQuantitativeAttributeAccuracy !other namespace
- result
- DQ_QuantitativeAttributeAccuracy
- result
+ DQ_FormatConsistency : AbstractDQ_LogicalConsistency
+ DQ_GriddedDataPositionalAccuracy : AbstractDQ_PositionalAccuracy
+ DQ_NonQuantitativeAttributeAccuracy : AbstractDQ_ThematicAccuracy !other
namespace
+ DQ_QuantitativeAttributeAccuracy : AbstractDQ_ThematicAccuracy
DQ_QuantitativeResult
value
valueType/valueRecordType
valueUnit
- DQ_RelativeInternalPositionalAccuracy
- result
- DQ_TemporalConsistency
- result
- DQ_TemporalValidity
- result
- DQ_ThematicClassificationCorrectness
- result
- DQ_TopologicalConsistency
- result
+ DQ_RelativeInternalPositionalAccuracy : AbstractDQ_PositionalAccuracy
+ DQ_TemporalConsistency : AbstractDQ_TemporalAccuracy
+ DQ_TemporalValidity : AbstractDQ_TemporalAccuracy
+ DQ_ThematicClassificationCorrectness : AbstractDQ_ThematicAccuracy
+ DQ_TopologicalConsistency : AbstractDQ_LogicalConsistency
QE_CoverageResult
resultContentDescription
resultFile
resultFormat
resultSpatialRepresentation
spatialRepresentationType
- QE_Usability !other namespace
- result
+ QE_Usability : AbstractDQ_Element !other namespace
http://www.isotc211.org/2005/gts
TM_Duration
TM_PeriodDuration
diff --git
a/core/sis-metadata/src/test/java/org/apache/sis/xml/RenameListGenerator.java
b/core/sis-metadata/src/test/java/org/apache/sis/xml/RenameListGenerator.java
index 98d6c26..3381457 100644
---
a/core/sis-metadata/src/test/java/org/apache/sis/xml/RenameListGenerator.java
+++
b/core/sis-metadata/src/test/java/org/apache/sis/xml/RenameListGenerator.java
@@ -37,11 +37,11 @@ import org.apache.sis.internal.xml.LegacyNamespaces;
/**
- * Creates the {@value TransformingReader#FILENAME} file. This class needs to
be executed only when the content
+ * Creates a file in the {@value TransformingReader#FILENAME} format. This
class can be executed if the content
* has changed, or for verifying the current file. Output format contains
namespaces first, then classes,
* then properties. Example:
*
- * {@preformat
+ * {@preformat text
* http://standards.iso.org/iso/19115/-3/cit/1.0
* CI_Address
* administrativeArea
@@ -49,6 +49,21 @@ import org.apache.sis.internal.xml.LegacyNamespaces;
* CI_Citation
* citedResponsibleParty
* }
+ *
+ * This class can be used as a starting point for generating a new file from
scratch.
+ * It should not be used for updating the existing file (unless a lot of
things have changed)
+ * because some of {@value TransformingReader#FILENAME} content have been
edited by hand.
+ * For generating a new file:
+ *
+ * {@preformat java
+ * public static void main(String[] args) throws Exception {
+ * RenameListGenerator gen = new
RenameListGenerator(Paths.get("/path/to/your/classes"));
+ * gen.add(Paths.get("root/package/of/classes/to/add"));
+ * try (final BufferedWriter out =
Files.newBufferedWriter(Paths.get("MyOutputFile.lst"))) {
+ * gen.print(out);
+ * }
+ * }
+ * }
*/
public final class RenameListGenerator {
/**
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingTypes.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingTypes.java
index bd6b00b..f1fa6f8 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingTypes.java
+++
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingTypes.java
@@ -17,6 +17,7 @@
package org.apache.sis.internal.referencing;
import java.util.Collection;
+import java.util.function.UnaryOperator;
import org.apache.sis.internal.jaxb.TypeRegistration;
import org.apache.sis.parameter.DefaultParameterValue;
import org.apache.sis.parameter.DefaultParameterValueGroup;
@@ -30,11 +31,11 @@ import org.opengis.referencing.ReferenceSystem;
* This class is declared in the {@code
META-INF/services/org.apache.sis.internal.jaxb.TypeRegistration} file.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
* @since 0.4
* @module
*/
-public final class ReferencingTypes extends TypeRegistration {
+public final class ReferencingTypes extends TypeRegistration implements
UnaryOperator<Object> {
/**
* Adds to the given collection the referencing types that should be given
to the initial JAXB context.
*/
@@ -46,14 +47,13 @@ public final class ReferencingTypes extends
TypeRegistration {
}
/**
- * Notifies that the {@code sis-referencing} module can marshal arbitrary
implementations
- * of some coordinate reference system interfaces.
+ * Returns the converter to apply before marshalling objects.
*
- * @return {@code true}.
+ * @return {@code this}.
*/
@Override
- protected boolean canMarshalInterfaces() {
- return true;
+ protected UnaryOperator<Object> beforeMarshal() {
+ return this;
}
/**
@@ -64,7 +64,7 @@ public final class ReferencingTypes extends TypeRegistration {
* @return the given value as a type that can be marshalled, or {@code
null}.
*/
@Override
- public Object toImplementation(final Object value) {
+ public Object apply(final Object value) {
return (value instanceof ReferenceSystem) ?
AbstractReferenceSystem.castOrCopy((ReferenceSystem) value) : null;
}
}
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedExecutor.java
b/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedExecutor.java
index 161fea5..cf26ccc 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedExecutor.java
+++
b/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedExecutor.java
@@ -39,7 +39,7 @@ import org.apache.sis.util.logging.Logging;
* (profiling shows that even a single thread has very low activity), which
reduces the interest of that class.
* Combination of {@code ThreadPoolExecutor} super-class with {@code
DelayedQueue} were not successful neither.
*
- * <p>Given that it:</p>
+ * <p>Given that:</p>
* <ul>
* <li>it seems difficult to configure {@code (Scheduled)ThreadPoolExecutor}
in such a way
* that two or more threads are created only when really needed,</li>
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedRunnable.java
b/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedRunnable.java
index 80c3114..816a9e3 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedRunnable.java
+++
b/core/sis-utility/src/main/java/org/apache/sis/internal/system/DelayedRunnable.java
@@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicLong;
* for more information.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 1.0
* @since 0.3
* @module
*/
@@ -49,9 +49,19 @@ public abstract class DelayedRunnable implements Delayed,
Runnable {
final long timestamp;
/**
+ * Creates a new task to be executed after the given delay.
+ *
+ * @param delay delay before execution of this task.
+ * @param unit unit of measurement of given {@code delay}.
+ */
+ protected DelayedRunnable(final int delay, final TimeUnit unit) {
+ timestamp = System.nanoTime() + unit.toNanos(delay);
+ }
+
+ /**
* Creates a new task to be executed at the given time.
* It is user's responsibility to add the {@link System#nanoTime()} value
- * to the delay he wants to wait.
+ * to the delay (s)he wants to wait.
*
* @param timestamp time of execution of this task, in nanoseconds
relative to {@link System#nanoTime()}.
*/
diff --git a/ide-project/NetBeans/build.xml b/ide-project/NetBeans/build.xml
index 3051311..8c66df3 100644
--- a/ide-project/NetBeans/build.xml
+++ b/ide-project/NetBeans/build.xml
@@ -116,6 +116,9 @@
<fileset
dir="${project.root}/application/sis-console/src/main/resources">
<include name="**/*.properties"/>
</fileset>
+ <fileset
dir="${project.root}/profiles/sis-french-profile/src/main/resources">
+ <include name="**/*.lst"/>
+ </fileset>
</copy>
diff --git
a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java
b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java
index 27c1783..1b7c4cb 100644
---
a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java
+++
b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java
@@ -25,7 +25,7 @@ import org.apache.sis.internal.jaxb.TypeRegistration;
* This class is declared in the {@code
META-INF/services/org.apache.sis.internal.jaxb.TypeRegistration} file.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
* @since 0.4
* @module
*/
@@ -42,4 +42,16 @@ public final class ProfileTypes extends TypeRegistration {
addTo.add(LegalConstraints.class);
addTo.add(SecurityConstraints.class);
}
+
+ /**
+ * Returns {@code true} for {@code export = false} in order to notify that
we provide
+ * a {@code "RenameOnImport.lst"} file that need to be read.
+ *
+ * @param export {@code true} for {@code "RenameOnImport.lst"}, {@code
false} for {@code "RenameOnImport.lst"}.
+ * @return {@code true} for {@code "RenameOnImport.lst"}, {@code false}
otherwise.
+ */
+ @Override
+ protected boolean hasRenameFile(boolean export) {
+ return !export;
+ }
}
diff --git
a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/package-info.java
b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/package-info.java
index 224e525..e94357b 100644
---
a/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/package-info.java
+++
b/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/package-info.java
@@ -23,7 +23,7 @@
*
* @author Cédric Briançon (Geomatys)
* @author Guilhem Legal (Geomatys)
- * @version 0.4
+ * @version 1.0
*
* @see org.apache.sis.profile.france
*
diff --git
a/profiles/sis-french-profile/src/main/resources/org/apache/sis/internal/profile/fra/RenameOnImport.lst
b/profiles/sis-french-profile/src/main/resources/org/apache/sis/internal/profile/fra/RenameOnImport.lst
new file mode 100644
index 0000000..fc0fa04
--- /dev/null
+++
b/profiles/sis-french-profile/src/main/resources/org/apache/sis/internal/profile/fra/RenameOnImport.lst
@@ -0,0 +1,10 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements;
+# and to You under the Apache License, Version 2.0.
+#
+http://www.cnig.gouv.fr/2005/fra
+ FRA_DataIdentification : MD_DataIdentification
+ FRA_DirectReferenceSystem : MD_ReferenceSystem
+ FRA_IndirectReferenceSystem : MD_ReferenceSystem
+ FRA_Constraints : MD_Constraints
+ FRA_LegalConstraints : MD_LegalConstraints
+ FRA_SecurityConstraints : MD_SecurityConstraints
diff --git
a/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DataIdentificationTest.java
b/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DataIdentificationTest.java
index 1c800a5..a9435ba 100644
---
a/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DataIdentificationTest.java
+++
b/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DataIdentificationTest.java
@@ -18,7 +18,6 @@ package org.apache.sis.internal.profile.fra;
import javax.xml.bind.JAXBException;
import org.apache.sis.test.xml.TestCase;
-import org.junit.Ignore;
import org.junit.Test;
import static org.apache.sis.test.MetadataAssert.*;
@@ -42,7 +41,6 @@ public final strictfp class DataIdentificationTest extends
TestCase {
* @see <a href="https://issues.apache.org/jira/browse/SIS-404">SIS-404</a>
*/
@Test
- @Ignore("Verify if we should discontinue this profile.")
public void testMarshalling() throws JAXBException {
final String xml =
"<fra:FRA_DataIdentification
xmlns:gmd=\"http://www.isotc211.org/2005/gmd\"" +