Class TransformingReader

java.lang.Object
org.apache.sis.xml.Transformer
org.apache.sis.xml.TransformingReader
All Implemented Interfaces:
Iterator<Object>, XMLEventReader

final class TransformingReader extends Transformer implements XMLEventReader
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 XMLEventReader, but with some namespaceURI 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.
Since:
1.0
Version:
1.0
  • Field Details

    • FILENAME

      static final String FILENAME
      Location of the file listing types and their properties contained in various namespaces. This is used for mapping legacy ISO 19139:2007 namespace to newer ISO 19115-3:2016 ones, where the same legacy "http://www.isotc211.org/2005/gmd" URI can be replaced by different URIs under "http://standards.iso.org/iso/19115/-3/…" depending on the class name. Syntax is documented in the readme.html page.
      See Also:
    • LEGACY_NAMESPACES

      private static final Set<String> LEGACY_NAMESPACES
      Namespaces of classes containing elements to move in different namespaces. This set will contain at least the following namespaces: More namespaces may appear depending on the optional module on the classpath. For example, sis-french-profile adds "http://www.cnig.gouv.fr/2005/fra".
    • NAMESPACES

      private static final Map<String,Map<String,String>> NAMESPACES
      The mapping from (type, attribute) pairs to new namespaces. This mapping will be applied only to namespaces enumerated in LEGACY_NAMESPACES.
      • Keys are XML names of types, ignoring "_TYPE" suffix (e.g. "CI_Citation")
      • Values are maps where:
        • Keys are XML names of properties (e.g. "title").
        • Values are either:
          • Namespace URI if Transformer.isNamespace(String) returns true 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.
      This map is initialized only once and should not be modified after that point.
    • in

      private final XMLEventReader in
      The reader from which to read events.
    • prefixes

      private final Map<String,String> prefixes
      The prefixes for namespace URIs. Keys are URIs used in JAXB annotations and values are prefixes computed by Namespaces.getPreferredPrefix(String, String) or any other means. We store the prefix both for performance reasons and for improving the guarantees that the URI → prefix mapping is stable.
      See Also:
    • nextEvent

      private XMLEvent nextEvent
      The next event to return after a call to peek(). This is used for avoiding to recompute the same object many times when peek() is invoked before a call to nextEvent(). This is also required for avoiding to duplicate additions and removals of elements in the outerElements list.
  • Constructor Details

  • Method Details

    • namespace

      static String namespace(String type)
      Returns the namespace for the given ISO type, or null if unknown. This is the namespace used in JAXB annotations.
      Parameters:
      type - a class name defined by ISO 19115 or related standards (e.g. "CI_Citation").
      Returns:
      a namespace for the given type, or null if unknown.
    • isWrapper

      private static boolean isWrapper(XMLEvent event, XMLEvent wrapper)
      Returns true if the given wrapper is a wrapper for the given event. This method is used for assertions only.
    • hasNext

      public boolean hasNext()
      Checks if there are more events.
      Specified by:
      hasNext in interface Iterator<Object>
      Specified by:
      hasNext in interface XMLEventReader
    • peek

      public XMLEvent peek() throws XMLStreamException
      Checks the next XMLEvent without removing it from the stream.
      Specified by:
      peek in interface XMLEventReader
      Throws:
      XMLStreamException
    • next

      public Object next()
      Returns the next element. Use nextEvent() instead.
      Specified by:
      next in interface Iterator<Object>
    • nextEvent

      public XMLEvent nextEvent() throws XMLStreamException
      Forwards the call and keep trace of the XML elements opened up to this point.
      Specified by:
      nextEvent in interface XMLEventReader
      Throws:
      XMLStreamException
    • nextTag

      public XMLEvent nextTag() throws XMLStreamException
      Forwards the call and keep trace of the XML elements opened up to this point.
      Specified by:
      nextTag in interface XMLEventReader
      Throws:
      XMLStreamException
    • convert

      private XMLEvent convert(XMLEvent event) throws XMLStreamException
      Keeps trace of XML elements opened up to this point and imports the given event. This method replaces the namespaces used in XML document by the namespace used by JAXB annotations. It is caller's responsibility to ensure that this method is invoked exactly once for each element, or at least for each START_ELEMENT and END_ELEMENT.
      Parameters:
      event - the event read from the underlying event reader.
      Returns:
      the converted event (may be the same instance).
      Throws:
      XMLStreamException
    • renamingMap

      final Map<String,Map<String,String>> renamingMap(String namespace)
      Returns the map loaded by Transformer.load(boolean, String, Set, int) if the given namespace is a known legacy namespace. This method returns a non-empty map only for legacy namespaces for which the "RenameOnImport.lst" file has been designed. This is necessary for avoiding confusion with classes of the same name defined in other standards. For example, the 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.
      Specified by:
      renamingMap in class Transformer
      Parameters:
      namespace - the namespace URI for which to get the substitution map.
      Returns:
      the substitution map for the given namespace, or an empty map if none.
    • relocate

      final String relocate(String namespace)
      Returns the new 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 class Transformer
    • prefixReplacement

      final String prefixReplacement(String previous, String namespace)
      Returns the prefix to use for a name in a new namespace. The prefix should have been specified (indirectly) by a previous call to importNS(Namespace, …), for example as a result of a NAMESPACE event. If not, we compute it now using the same algorithm than in importNS.
      Specified by:
      prefixReplacement in class Transformer
      Parameters:
      previous - the prefix associated to old namespace.
      namespace - the new namespace URI.
      Returns:
      prefix to use for the new namespace.
    • importNS

      private Namespace importNS(Namespace namespace, String oldURI, String newURI)
      Converts a namespace read from the XML document to the namespace used by JAXB annotations. This methods can convert the namespace for which there is a bijective mapping, for example "http://www.isotc211.org/2005/gco" to "http://standards.iso.org/iso/19115/-3/gco/1.0". However, some namespaces like "http://www.isotc211.org/2005/gmd" may be left unchanged, because that namespace from legacy ISO 19139:2007 can be mapped to many different namespaces in newer ISO 19115-3:2016 standard. However, in some cases the context allows us to determines which newer namespace is used. In such case, that mapping is specified by the (oldURI, newURI) pair.
      Parameters:
      namespace - the namespace to import.
      oldURI - an old URI which has been renamed as newURI, or null if none.
      newURI - the new URI for oldURI, or null if newURI is null.
    • importNS

      private List<Namespace> importNS(Iterator<Namespace> namespaces, String oldURI, String newURI, boolean changed)
      Imports the namespaces read from the XML document.
      Parameters:
      namespaces - the namespaces to transform.
      oldURI - an old URI which has been renamed as newURI, or null if none.
      newURI - the new URI for oldURI, or null if newURI is null.
      changed - whether to unconditionally pretend that there is a change.
      Returns:
      the updated namespaces, or null if there is no change.
    • getElementText

      public String getElementText() throws XMLStreamException
      Reads the content of a text-only element. Forwards from the underlying reader as-is.
      Specified by:
      getElementText in interface XMLEventReader
      Throws:
      XMLStreamException
    • getProperty

      public Object getProperty(String name)
      Get the value of a feature/property from the underlying implementation.
      Specified by:
      getProperty in interface XMLEventReader
    • close

      public void close() throws XMLStreamException
      Frees any resources associated with this reader. This method does not close the underlying input source.
      Specified by:
      close in interface XMLEventReader
      Overrides:
      close in class Transformer
      Throws:
      XMLStreamException