Details
-
Sub-task
-
Status: Open
-
Major
-
Resolution: Unresolved
-
1.0, 1.1
-
None
Description
The use of GML 3.2 implies the use of ISO 19139:2007 metadata for describing the extent, positional accuracy, identifiers, etc. For now (in Apache SIS 1.0), we use an @UseLegacyMetadata annotations (internal API). When this annotation is found on the object to marshal, PooledMarshaller automatically set the metadata version to 2007. However this works only for the root element. If the user specifies another object which itself contains GML, this will not work.
If we want this automatic selection of ISO 19139:2007 metadata to work no matter where the GML elements appear, we need a different approach. One possible approach is to update the org.apache.sis.internal.jaxb.Context state in a way similar to what we do for Locale. This can be done by addition the following constructor and modifying the push(…) method like below (only the main elements that are modified are shown below):
public final class Context extends MarshalContext { /** * The locale to use for marshalling, or {@code null} if no locale were explicitly specified. */ private final Locale locale; /** * Creates a new context identical to the given parent except for the locale and bitmask. */ private Context(final Context parent, final int bitMasks, final Locale locale) { this.bitMasks = bitMasks; this.locale = locale; this.timezone = parent.timezone; this.schemas = parent.schemas; this.versionGML = parent.versionGML; this.resolver = parent.resolver; this.converter = parent.converter; this.warningListener = parent.warningListener; this.identifiers = parent.identifiers; this.identifiedObjects = parent.identifiedObjects; this.previous = parent; } @Override public final Locale getLocale() { return locale; } /** * Sets the locale to the given value, optionally with additional bits to set. * The old locales and bit masks are remembered and will be restored by the next call to {@link #pull()}. * This method can be invoked when marshalling object that need to marshall their children in a different * locale, like below: * * {@preformat java * private void beforeMarshal(Marshaller marshaller) { * Context.push(0, language); * } * * private void afterMarshal(Marshaller marshaller) { * Context.pull(); * } * } * * @param bitsToSet new bits to set, or 0 for no change. * @param locale the locale to set, or {@code null} for keeping the current locale. */ public static void push(final int bitsToSet, Locale locale) { Context current = current(); if (current != null) { if (locale == null) { locale = current.getLocale(); } current = new Context(current, current.bitMasks | bitsToSet, locale); CURRENT.set(current); } } /** * Restores the locale which was used prior the call to {@link #push(int, Locale)}. */ public static void pull() { final Context current = current(); if (current != null) { CURRENT.set(current.previous); } } }
Then, in the org.apache.sis.referencing package:
public class AbstractIdentifiedObject implements IdentifiedObject { /** * Invoked by JAXB {@link javax.xml.bind.Marshaller} before this object is marshalled to XML. * This method sets the locale to be used for XML marshalling to the metadata language. */ @SuppressWarnings("unused") private void beforeMarshal(final Marshaller marshaller) { Context.push(Context.LEGACY_METADATA, null); } /** * Invoked by JAXB {@link javax.xml.bind.Marshaller} after this object has been marshalled to * XML. This method restores the locale to be used for XML marshalling to its previous value. */ @SuppressWarnings("unused") private void afterMarshal(final Marshaller marshaller) { Context.pull(); } }
This approach almost work. The problem is that changing Context state is not sufficient. We also need to change on-the-fly the TransformVersion used by TransformingReader in the org.apache.sis.xml package, and restore the previous state once the GML object marshalling is finished. Since the impact needs more investigation, this task has been deferred to a later version.