Package org.apache.sis.xml
Class TransformingWriter
java.lang.Object
org.apache.sis.xml.Transformer
org.apache.sis.xml.TransformingWriter
- All Implemented Interfaces:
XMLEventConsumer
,XMLEventWriter
A writer replacing the namespaces used by JAXB by other namespaces to be used in the XML document
at marshalling time. This class forwards every method calls to the wrapped
XMLEventWriter
,
with all namespaceURI
arguments transformed before to be delegated.
See Transformer
for more information.- Since:
- 1.0
- Version:
- 1.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final class
Wraps theStartElement
produced by JAXB for using the namespaces used in the XML document.private static final class
A sentinel value in thedeferred
queue meaning that after reaching this point, we need to reevaluate if the remaining elements should be written immediately of deferred again. -
Field Summary
FieldsModifier and TypeFieldDescriptionEvents for which writing is deferred as long as there is elements to skip.Elements that appear in different order in ISO 19139:2007 (or other legacy standards) compared to ISO 19115-3:2016 (or other newer standards).private static final String
Location of the file listing types and their properties contained in legacy namespaces.private boolean
The mapping from (type, attribute) pairs to legacy namespaces.private final XMLEventWriter
Where events are sent.private int
Number of times thatsubtreeRootName
has been found.private QName
Name of the the root element of a sub-tree to handle in a special way, ornull
if none.If non-null, elements to skip before we can write the deferred events.Keep track of namespace URIs that have already been declared so they don't get duplicated.Fields inherited from class org.apache.sis.xml.Transformer
NO_NAMESPACE, renamedAttributes, version
-
Constructor Summary
ConstructorsConstructorDescriptionTransformingWriter
(XMLEventWriter out, TransformVersion version) Creates a new writer for the given version of the standards. -
Method Summary
Modifier and TypeMethodDescriptionvoid
Converts an event from the namespaces used in JAXB annotations to the namespaces used in the XML document to write.void
add
(XMLEventReader reader) Adds an entire stream to an output stream.void
close()
Frees any resources associated with this writer.Returns the namespaces to write in the XML document, ornull
if there is no change.private Namespace
exportIfNew
(Namespace namespace) Returns the namespace to write in the XML document.void
flush()
Writes any cached events to the underlying output mechanism.Returns a naming context suitable for consumption by JAXB marshallers.Gets the prefix the URI is bound to.(package private) final String
prefixReplacement
(String previous, String namespace) Returns the prefix to use for a name in a new namespace.(package private) final String
Returns the old namespace for elements (types and properties) in the given namespace.renamingMap
(String namespace) Returns the map loaded byTransformer.load(boolean, String, Set, int)
.void
Binds a URI to the default namespace.void
setNamespaceContext
(NamespaceContext context) Sets the current namespace context for prefix and URI bindings.void
Sets the prefix the URI is bound to.private boolean
writeDeferred
(QName element) Writes immediately all elements that were deferred.Methods inherited from class org.apache.sis.xml.Transformer
attributes, close, convert, convert, isNamespace, load, notify, open, removeTrailingSlash
-
Field Details
-
FILENAME
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"http://standards.iso.org/iso/19115/-3/…"
URI is used in places where legacy schema had two distinct URIs:"http://www.isotc211.org/2005/gmd"
and"http://standards.iso.org/iso/19115/-2/gmi/1.0"
.- See Also:
-
NAMESPACES
The mapping from (type, attribute) pairs to legacy namespaces.- Keys are XML names of types, ignoring
"_TYPE"
suffix (e.g."MI_Georectified"
) - Values are maps where:
- Keys are XML names of properties (e.g.
"checkPoint"
) - Values are either:
- Namespace URI if
Transformer.isNamespace(String)
returnstrue
for that value. - New name of the element otherwise. In such case, the map must be queried again with that new name for obtaining the namespace.
- Namespace URI if
- Keys are XML names of properties (e.g.
- Keys are XML names of types, ignoring
-
ELEMENTS_TO_REORDER
Elements that appear in different order in ISO 19139:2007 (or other legacy standards) compared to ISO 19115-3:2016 (or other newer standards). Key are names of elements to reorder. Values are the elements to skip before to write the element to reorder.Example: InWhile this map is used for reordering elements according legacy standards, theSV_ServiceIdentification
,<srv:couplingType>
appears before<srv:coupledResource>
according ISO 19115-3:2016. But in ISO 19139:2007, it was the reverse order. Since Apache SIS writes elements in the order defined by the newer standard,<couplingType>
is encountered first. The set associated to that key tells us that, when writing legacy ISO 19139 document, we should skip<coupledResource>
before to write<srv:couplingType>
.QName
keys and values use the namespaces of newer standards. This is because newer standards like ISO 19115-3 uses many namespaces where legacy ISO 19139:2007 used only one namespace, so using the newer names reduce the risk of confusion. -
out
Where events are sent. -
uniqueNamespaces
Keep track of namespace URIs that have already been declared so they don't get duplicated. This map is recycled in two different contexts:- In a sequence of
NAMESPACE
events. - In the namespaces of a start element.
- In a sequence of
-
isDeferring
private boolean isDeferringtrue
if events should be sent todeferred
instead of toout
. This is set totrue
when we see aStartElement
having one of the names contained in theELEMENTS_TO_REORDER
keys set. -
deferred
Events for which writing is deferred as long as there is elements to skip. The intent is to reorder elements that appear in a different order in legacy standards compared to newer standards. This is a FIFO (First-In-First-Out) queue. Namespaces are the exported ones (the ones after conversions from JAXB to the XML document to write).Elements are instance of
XMLEvent
orTransformingWriter.NewDeferred
.- See Also:
-
toSkip
If non-null, elements to skip before we can write the deferred events. Should be theELEMENTS_TO_REORDER
value associated to the element to defer. A null value means that events can be written immediately toout
. -
subtreeRootName
Name of the the root element of a sub-tree to handle in a special way, ornull
if none. At first, this is the name of theStartElement
of a sub-tree to defer (i.e. one of the keys in theELEMENTS_TO_REORDER
map). Later, it becomes the names of sub-trees to skip (i.e. thetoSkip
values). -
subtreeNesting
private int subtreeNestingNumber of times thatsubtreeRootName
has been found. A value of 1 means that we started receiving events for that subtree. A value of 0 means that we finished receiving events for that subtree. A value greater than 1 means that there is nested sub-trees (should not happen).
-
-
Constructor Details
-
TransformingWriter
TransformingWriter(XMLEventWriter out, TransformVersion version) Creates a new writer for the given version of the standards.
-
-
Method Details
-
renamingMap
Returns the map loaded byTransformer.load(boolean, String, Set, int)
.- Specified by:
renamingMap
in classTransformer
- Parameters:
namespace
- the namespace URI for which to get the substitution map.- Returns:
- the substitution map for the given namespace.
-
relocate
Returns the old namespace for elements (types and properties) in the given namespace. This method is used only for default relocations, i.e. the fallback to apply when no explicit rule has been found.- Specified by:
relocate
in classTransformer
-
prefixReplacement
Returns the prefix to use for a name in a new namespace.- Specified by:
prefixReplacement
in classTransformer
- Parameters:
previous
- the prefix associated to old namespace.namespace
- the new namespace URI.- Returns:
- prefix to use for the new namespace.
- Throws:
XMLStreamException
- if an error occurred while fetching the prefix.
-
exportIfNew
Returns the namespace to write in the XML document. This may imply a prefix change. If there is no namespace change, then this method returns the given instance as-is. To test if the returned namespace is a new one, callers should check if the size ofuniqueNamespaces
changed.- Parameters:
namespace
- the namespace to export.
-
export
Returns the namespaces to write in the XML document, ornull
if there is no change. If non-null, the result may contain less namespaces because duplicated entries are omitted (duplication may occur as a result of replacing various ISO 19115-3 namespaces by the legacy ISO 19139:2007"gmd"
unique namespace).- Parameters:
namespaces
- the namespaces to transform.changed
- whether to unconditionally pretend that there is a change.- Returns:
- the updated namespaces, or
null
if there is no change.
-
add
Converts an event from the namespaces used in JAXB annotations to the namespaces used in the XML document to write. This method may wrap the given event into another event for changing the namespace and prefix, or use the event as-is if no change is needed.- Specified by:
add
in interfaceXMLEventConsumer
- Specified by:
add
in interfaceXMLEventWriter
- Parameters:
event
- the event using JAXB namespaces.- Throws:
XMLStreamException
-
writeDeferred
Writes immediately all elements that were deferred. This happen because the nextStartElement
to write should be after the deferred element, or because we are about to exit the parent element that contains the deferred element, or becauseflush()
has been invoked.- Parameters:
element
- theStartElement
element name, ornull
for other events.- Returns:
true
if the given element starts a new subtree to skip.- Throws:
XMLStreamException
- See Also:
-
add
Adds an entire stream to an output stream.- Specified by:
add
in interfaceXMLEventWriter
- Throws:
XMLStreamException
-
getPrefix
Gets the prefix the URI is bound to. Since our (imported URI) ⟶ (exported URI) transformation is not bijective, implementing this method could potentially result in the same prefix for different URIs, which is illegal for a XML document and potentially dangerous. Thankfully JAXB seems to never invoke this method in our tests.- Specified by:
getPrefix
in interfaceXMLEventWriter
- Throws:
XMLStreamException
-
setPrefix
Sets the prefix the URI is bound to. This method replaces the given URI if needed, then forwards the call. Note that it may result in the same URI to be bound to many prefixes. For example, ISO 19115-3:2016 has many URIs, each with a different prefix ("mdb"
,"cit"
, etc.). But all those URIs may be replaced by the unique URI used in legacy ISO 19139:2007. Since this method does not replace the prefix (it was"gmd"
in ISO 19139:2007), the various ISO 19115-3:2016 prefixes are all bound to the same legacy ISO 19139:2007 URI. This is confusing, but not ambiguous for XML parsers.Implemented as a matter of principle, but JAXB did not invoked this method in our tests.
- Specified by:
setPrefix
in interfaceXMLEventWriter
- Throws:
XMLStreamException
-
setDefaultNamespace
Binds a URI to the default namespace. Current implementation replaces the given URI (e.g. an ISO 19115-3:2016 one) by the exported URI (e.g. legacy ISO 19139:2007 one), then forwards the call.Implemented as a matter of principle, but JAXB did not invoked this method in our tests.
- Specified by:
setDefaultNamespace
in interfaceXMLEventWriter
- Throws:
XMLStreamException
-
setNamespaceContext
Sets the current namespace context for prefix and URI bindings. This method unwraps the original context and forwards the call.Implemented as a matter of principle, but JAXB did not invoked this method in our tests.
- Specified by:
setNamespaceContext
in interfaceXMLEventWriter
- Throws:
XMLStreamException
-
getNamespaceContext
Returns a naming context suitable for consumption by JAXB marshallers. TheXMLEventWriter
wrapped by thisTransformingWriter
has been created for writing in a file. Consequently, its naming context manages namespaces used in the XML document. But the JAXB marshaller using thisTransformingWriter
facade expects the namespaces declared in JAXB annotations. Consequently, this method returns an adapter that converts namespaces on the fly.- Specified by:
getNamespaceContext
in interfaceXMLEventWriter
- See Also:
-
flush
Writes any cached events to the underlying output mechanism.- Specified by:
flush
in interfaceXMLEventWriter
- Throws:
XMLStreamException
-
close
Frees any resources associated with this writer.- Specified by:
close
in interfaceXMLEventWriter
- Overrides:
close
in classTransformer
- Throws:
XMLStreamException
-