/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.xml;

import java.util.Map;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.Queue;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.Namespace;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.internal.xml.LegacyNamespaces;

import static javax.xml.stream.XMLStreamConstants.*;


/**
 * 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 {@link XMLEventWriter},
 * with all {@code namespaceURI} arguments transformed before to be delegated.
 *
 * See {@link Transformer} for more information.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @author  Cullen Rombach (Image Matters)
 * @version 1.0
 * @since   1.0
 * @module
 */
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 schema had two distinct URIs:  {@code "http://www.isotc211.org/2005/gmd"}
     * and {@code "http://standards.iso.org/iso/19115/-2/gmi/1.0"}.
     */
    private static final String FILENAME = "RenameOnExport.lst";

    /**
     * The mapping from (<var>type</var>, <var>attribute</var>) pairs to legacy namespaces.
     *
     * <ul>
     *   <li>Keys are XML names of types, ignoring {@code "_TYPE"} suffix (e.g. {@code "MI_Georectified"})</li>
     *   <li>Values are maps where:<ul>
     *     <li>Keys are XML names of properties (e.g. {@code "checkPoint"})</li>
     *     <li>Values are either:<ul>
     *       <li>Namespace URI if {@link #isNamespace(String)} returns {@code true} for that value.</li>
     *       <li>New name of the element otherwise. In such case, the map must be queried again with
     *           that new name for obtaining the namespace.</li>
     *     </ul></li>
     *   </ul></li>
     * </ul>
     *
     * This map is initialized only once and should not be modified after that point.
     */
    private static final Map<String, Map<String,String>> NAMESPACES = load(true, FILENAME, Collections.emptySet(), 60);

    /**
     * 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.
     *
     * <div class="note"><b>Example:</b>
     * In {@code SV_ServiceIdentification}, {@code <srv:couplingType>} appears before {@code <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, {@code <couplingType>} is encountered first. The set associated
     * to that key tells us that, when writing legacy ISO 19139 document, we should skip {@code <coupledResource>}
     * before to write {@code <srv:couplingType>}.</div>
     *
     * While this map is used for reordering elements according legacy standards, the {@link 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.
     *
     * @see #toSkip
     * @see #deferred
     *
     * @todo Hard-coded for now. Should move to a resource file in a future version.
     */
    private static final Map<QName, Set<QName>> ELEMENTS_TO_REORDER;
    static {
        final Map<QName, Set<QName>> m = new HashMap<>(4);
        m.put(new QName(Namespaces.SRV, "couplingType",  "srv"), Collections.singleton(new QName(Namespaces.SRV, "coupledResource", "srv")));
        m.put(new QName(Namespaces.SRV, "connectPoint",  "srv"), Collections.singleton(new QName(Namespaces.SRV, "parameter",       "srv")));
        /*
         * ISO 19139:2997 declared `topicCategory` and `extent` in MD_DataIdentification subclass, while ISO 19115-3
         * moves them to the MD_Identification parent class. In order to write topicCategory at location expected by
         * legacy metadata, we need to skip all properties declared after `topicCategory` in that parent class.
         */
        QName first;
        HashSet<QName> toSkip = new HashSet<>(Arrays.asList(
            first = new QName(      Namespaces.MRI, "extent",                  "mri"),
                    new QName(      Namespaces.MRI, "additionalDocumentation", "mri"),
                    new QName(      Namespaces.MRI, "processingLevel",         "mri"),
                    new QName(      Namespaces.MRI, "resourceMaintenance",     "mri"),
                    new QName(      Namespaces.MRI, "graphicOverview",         "mri"),
                    new QName(      Namespaces.MRI, "resourceFormat",          "mri"),
                    new QName(      Namespaces.MRI, "descriptiveKeywords",     "mri"),
                    new QName(      Namespaces.MRI, "resourceSpecificUsage",   "mri"),
                    new QName(      Namespaces.MRI, "resourceConstraints",     "mri"),
                    new QName(      Namespaces.MRI, "associatedResource",      "mri"),
                    new QName(LegacyNamespaces.GMD, "aggregationInfo",         "gmd"),
                    new QName(LegacyNamespaces.GMD, "language",                "gmd"),
                    new QName(LegacyNamespaces.GMD, "characterSet",            "gmd"),
                    new QName(      Namespaces.MRI, "defaultLocale",           "mri"),
                    new QName(      Namespaces.MRI, "otherLocale",             "mri")));
        /*
         * The `extent` element is right after `topicCategory` in ISO 19115-3:2016, but there was an
         * `environmentDescription` between them in legacy ISO 19139:2007. So we add the latter in the
         * list of elements to skip for `extent`.
         */
        m.put(new QName(Namespaces.MRI, "topicCategory", "mri"), CollectionsExt.clone(toSkip));
        toSkip.remove(first);
        toSkip.add(new QName(Namespaces.MRI, "environmentDescription", "mri"));
        m.put(first, toSkip);                                                     // For <mri:extent>
        ELEMENTS_TO_REORDER = m;
    }

    /**
     * Where events are sent.
     */
    private final XMLEventWriter out;

    /**
     * Keep track of namespace URIs that have already been declared so they don't get duplicated.
     * This map is recycled in two different contexts:
     *
     * <ul>
     *   <li>In a sequence of {@code NAMESPACE} events.</li>
     *   <li>In the namespaces of a start element.</li>
     * </ul>
     */
    private final Map<String,Namespace> uniqueNamespaces;

    /**
     * {@code true} if events should be sent to {@link #deferred} instead of to {@link #out}.
     * This is set to {@code true} when we see a {@link StartElement} having one of the names
     * contained in the {@link #ELEMENTS_TO_REORDER} keys set.
     */
    private boolean isDeferring;

    /**
     * Events for which writing is deferred as long as there is elements {@linkplain #toSkip 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).
     *
     * <p>Elements are instance of {@link XMLEvent} or {@link NewDeferred}.</p>
     *
     * @see #ELEMENTS_TO_REORDER
     */
    private final Queue<Object> deferred;

    /**
     * If non-null, elements to skip before we can write the {@linkplain #deferred} events.
     * Should be the {@link #ELEMENTS_TO_REORDER} value associated to the element to defer.
     * A null value means that events can be written immediately to {@link #out}.
     */
    private Set<QName> toSkip;

    /**
     * Name of the the root element of a sub-tree to handle in a special way, or {@code null} if none.
     * At first, this is the name of the {@link StartElement} of a sub-tree to defer (i.e. one of the
     * keys in the {@link #ELEMENTS_TO_REORDER} map). Later, it becomes the names of sub-trees to skip
     * (i.e. the {@link #toSkip} values).
     */
    private QName subtreeRootName;

    /**
     * Number of times that {@link #subtreeRootName} 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).
     */
    private int subtreeNesting;

    /**
     * Creates a new writer for the given version of the standards.
     */
    TransformingWriter(final XMLEventWriter out, final TransformVersion version) {
        super(version);
        this.out = out;
        uniqueNamespaces = new LinkedHashMap<>();
        deferred = new ArrayDeque<>();
    }

    /**
     * Returns the map loaded by {@link #load(boolean, String, Set, int)}.
     *
     * @param  namespace  the namespace URI for which to get the substitution map.
     * @return the substitution map for the given namespace.
     */
    @Override
    @SuppressWarnings("ReturnOfCollectionOrArrayField")
    final Map<String, Map<String,String>> renamingMap(final String namespace) {
        return NAMESPACES;
    }

    /**
     * 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.
     */
    @Override
    final String relocate(final String namespace) {
        return version.exportNS(namespace);
    }

    /**
     * Returns the prefix to use for a name in a new namespace.
     *
     * @param  previous   the prefix associated to old namespace.
     * @param  namespace  the new namespace URI.
     * @return prefix to use for the new namespace.
     * @throws XMLStreamException if an error occurred while fetching the prefix.
     */
    @Override
    final String prefixReplacement(final String previous, final String namespace) throws XMLStreamException {
        /*
         * The wrapped XMLEventWriter maintains a mapping from prefixes to namespace URIs.
         * Arguments are exported URIs (e.g. from legacy ISO 19139:2007) and return values
         * are prefixes computed by `Namespaces.getPreferredPrefix(…)` or any other means.
         * We fetch those prefixes for performance reasons and for improving the guarantees
         * that the URI → prefix mapping is stable, since JAXB seems to require them for
         * writing namespaces in XML.
         */
        String prefix = out.getPrefix(namespace);
        if (prefix == null) {
            prefix = Namespaces.getPreferredPrefix(namespace, previous);
            out.setPrefix(prefix, namespace);
            /*
             * The above call for `getPreferredPrefix` above is required: JAXB seems to need the prefixes
             * for recognizing namespaces. The prefix shall be computed in the same way than `exportIfNew`.
             * We enter in this block only for the root element, before to parse `xmlns` attributes. For
             * all other elements after the root elements, above call to `out.getPrefix(uri)` should succeed.
             */
        }
        return prefix;
    }

    /**
     * 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 of
     * {@link #uniqueNamespaces} changed.
     *
     * @param  namespace  the namespace to export.
     */
    private Namespace exportIfNew(final Namespace namespace) {
        notify(namespace);
        String uri = namespace.getNamespaceURI();
        if (uri != null && !uri.isEmpty()) {
            /*
             * Ignore trailing slash when checking if there is a namespace change.
             * But if we do not find a namespace change, keep the trailing slash as
             * given in the Namespace since that slash may be intentional.
             */
            final String trimed = removeTrailingSlash(uri);
            final String exported = relocate(trimed);
            if (exported != trimed) {
                return uniqueNamespaces.computeIfAbsent(exported, (k) -> {
                    return new TransformedEvent.NS(namespace, Namespaces.getPreferredPrefix(k, namespace.getPrefix()), k);
                    /*
                     * The new prefix selected by above line will be saved by out.add(Namespace)
                     * after this method has been invoked by the NAMESPACE case of add(XMLEvent).
                     */
                });
            }
            final Namespace c = uniqueNamespaces.put(uri, namespace);   // No namespace change needed. Overwrite wrapper if any.
            if (c != null) return c;
        }
        return namespace;
    }

    /**
     * Returns the namespaces to write in the XML document, or {@code null} 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 {@code "gmd"} unique namespace).
     *
     * @param  namespaces  the namespaces to transform.
     * @param  changed     whether to unconditionally pretend that there is a change.
     * @return the updated namespaces, or {@code null} if there is no change.
     */
    private List<Namespace> export(final Iterator<Namespace> namespaces, boolean changed) {
        if (!namespaces.hasNext()) {
            return changed ? Collections.emptyList() : null;
        }
        do {
            final Namespace namespace = namespaces.next();
            changed |= (namespace != exportIfNew(namespace));
        } while (namespaces.hasNext());
        if (changed) {
            assert !uniqueNamespaces.isEmpty();
            final Namespace[] exported = uniqueNamespaces.values().toArray(new Namespace[uniqueNamespaces.size()]);
            uniqueNamespaces.clear();
            return Arrays.asList(exported);
        } else {
            uniqueNamespaces.clear();
            return null;
        }
    }

    /**
     * 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.
     *
     * @param  event  the event using JAXB namespaces.
     */
    @Override
    public void add(XMLEvent event) throws XMLStreamException {
        switch (event.getEventType()) {
            case ATTRIBUTE: {
                event = convert((Attribute) event);
                break;
            }
            case NAMESPACE: {
                final int n = uniqueNamespaces.size();
                event = exportIfNew((Namespace) event);
                if (uniqueNamespaces.size() == n) {
                    return;                                     // An event has already been created for that namespace.
                }
                break;
            }
            case END_ELEMENT: {
                final EndElement e = event.asEndElement();
                final QName originalName = e.getName();
                final QName name = convert(originalName);
                final List<Namespace> namespaces = export(e.getNamespaces(), name != originalName);
                if (namespaces != null) {
                    event = new TransformedEvent.End(e, name, namespaces);
                }
                if (toSkip != null) {                           // Check if a previous START_ELEMENT found a need to reorder.
                    if (originalName.equals(subtreeRootName)) {
                        subtreeNesting--;                       // May reach 0 but be followed by another element to skip.
                    } else if (subtreeNesting == 0) {
                        writeDeferred(null);                    // About to exit the parent element containing deferred element.
                    }
                }
                close(originalName);                            // Must be invoked only after `convert(QName)`
                break;
            }
            case START_ELEMENT: {
                uniqueNamespaces.clear();                       // Discard entries created by NAMESPACE events.
                final StartElement e = event.asStartElement();
                final QName originalName = e.getName();
                open(originalName);                             // Must be invoked before `convert(QName)`.
                final QName name = convert(originalName);
                boolean changed = name != originalName;
                for (final Iterator<Attribute> it = e.getAttributes(); it.hasNext();) {
                    final Attribute a = it.next();
                    final Attribute ae = convert(a);
                    changed |= (a != ae);
                    renamedAttributes.add(ae);
                }
                final List<Namespace> namespaces = export(e.getNamespaces(), changed);
                if (namespaces != null) {
                    event = new Event(e, name, namespaces, attributes(), version);
                } else {
                    renamedAttributes.clear();          // Note: above call to attributes() also cleared that list.
                }
                /*
                 * At this point, we finished to export the event (i.e. to convert namespaces to the URI
                 * used in the XML documents). The remaining code in this block is for handling the case
                 * where the elements should not be written immediately, but after some other events.
                 * This happen when legacy standards ordered some elements differently.
                 */
                if (toSkip == null) {
                    toSkip = ELEMENTS_TO_REORDER.get(originalName);
                    if (toSkip != null) {
                        subtreeRootName = originalName;                 // Found a new element to defer.
                        subtreeNesting = 1;
                        isDeferring = true;
                    }
                } else if (subtreeNesting == 0) {
                    /*
                     * If the current element should not be skipped (toSkip.contains(…) = false), then
                     * we need to write all deferred elements. Usually `writeDeferred(…)` returns false,
                     * so the block inside the `if` is executed only if `toSkip.contains(…)` is true.
                     * But in few cases, we still need to be in "skipping" state after `writeDeferred`.
                     */
                    if (toSkip.contains(originalName) || writeDeferred(originalName)) {
                        /*
                         * Found an element to skip. That element will be written immediately (except if
                         * it is another element which needs reordering), and the elements currently in
                         * the `deferred` list will continue to be deferred at least until we reached the
                         * end of the current element. It may happen that the current element is itself
                         * an element that needs reordering (i.e. we may have nested reordered elements),
                         * in which case we reset the `isDeferring` flag to `true`.
                         */
                        subtreeRootName = originalName;
                        subtreeNesting = 1;
                        final Set<QName> interleaved = ELEMENTS_TO_REORDER.get(originalName);
                        if (interleaved != null) {
                            isDeferring = true;
                            deferred.add(new NewDeferred(interleaved));
                        }
                    }
                } else if (originalName.equals(subtreeRootName)) {
                    subtreeNesting++;
                }
                break;
            }
        }
        if (isDeferring) {
            deferred.add(event);
            isDeferring = (subtreeNesting != 0);
        } else {
            out.add(event);
        }
    }

    /**
     * A sentinel value in the {@link TransformingWriter#deferred} queue meaning that after reaching this point,
     * we need to reevaluate if the remaining elements should be written immediately of deferred again.
     * This happen when some elements to move are interleaved. For example in {@code MD_DataIdentification}:
     *
     * <ol>
     *   <li>{@code topicCategory} needs to move before {@code environmentDescription}</li>
     *   <li>{@code extent} needs to move before {@code supplementalInformation}</li>
     *   <li>{@code graphicOverviews}</li>
     *   <li>{@code resourceFormats}</li>
     *   <li><i>etc.</i>
     *   <li>{@code environmentDescription}</li>
     *   <li>{@code supplementalInformation}</li>
     * </ol>
     *
     * This class is for handling the {@code extent} case in such scenario.
     */
    private static final class NewDeferred {
        /** The value to assign to {@link TransformingWriter#deferred} after we reach this point. */
        final Set<QName> toSkip;

        /** Creates a new sentinel value for a reevaluation point. */
        NewDeferred(final Set<QName> toSkip) {
            this.toSkip = toSkip;
        }
    }

    /**
     * Writes immediately all elements that were deferred. This happen because the next {@link StartElement}
     * to write should be after the deferred element, or because we are about to exit the parent element that
     * contains the deferred element, or because {@link #flush()} has been invoked.
     *
     * @param  element  the {@link StartElement} element name, or {@code null} for other events.
     * @return {@code true} if the given element starts a new subtree to skip.
     *
     * @see #ELEMENTS_TO_REORDER
     */
    private boolean writeDeferred(final QName element) throws XMLStreamException {
        subtreeRootName = null;
        toSkip = null;
        Object v;
        while ((v = deferred.poll()) != null) {
            if (!(v instanceof NewDeferred)) {
                out.add((XMLEvent) v);
            } else if (element != null) {
                final Set<QName> s = ((NewDeferred) v).toSkip;
                if (s.contains(element)) {
                    toSkip = s;
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Adds an entire stream to an output stream.
     */
    @Override
    public void add(final XMLEventReader reader) throws XMLStreamException {
        while (reader.hasNext()) {
            add(reader.nextEvent());
        }
    }

    /**
     * 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.
     */
    @Override
    public String getPrefix(final String uri) throws XMLStreamException {
        throw new XMLStreamException(Errors.format(Errors.Keys.UnsupportedOperation_1, "getPrefix"));
    }

    /**
     * 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 ({@code "mdb"}, {@code "cit"}, <i>etc.</i>). 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 {@code "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.
     *
     * <p>Implemented as a matter of principle, but JAXB did not invoked this method in our tests.</p>
     */
    @Override
    public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
        out.setPrefix(prefix, relocate(uri));
    }

    /**
     * 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.
     *
     * <p>Implemented as a matter of principle, but JAXB did not invoked this method in our tests.</p>
     */
    @Override
    public void setDefaultNamespace(final String uri) throws XMLStreamException {
        out.setDefaultNamespace(relocate(uri));
    }

    /**
     * Sets the current namespace context for prefix and URI bindings.
     * This method unwraps the original context and forwards the call.
     *
     * <p>Implemented as a matter of principle, but JAXB did not invoked this method in our tests.</p>
     */
    @Override
    public void setNamespaceContext(final NamespaceContext context) throws XMLStreamException {
        out.setNamespaceContext(TransformingNamespaces.asXML(context, version));
    }

    /**
     * Returns a naming context suitable for consumption by JAXB marshallers.
     * The {@link XMLEventWriter} wrapped by this {@code TransformingWriter} has been created for writing in a file.
     * Consequently its naming context manages namespaces used in the XML document. But the JAXB marshaller using
     * this {@code TransformingWriter} facade expects the namespaces declared in JAXB annotations. Consequently this
     * method returns an adapter that converts namespaces on the fly.
     *
     * @see Event#getNamespaceContext()
     */
    @Override
    public NamespaceContext getNamespaceContext() {
        return TransformingNamespaces.asJAXB(out.getNamespaceContext(), version);
    }

    /**
     * Wraps the {@link StartElement} produced by JAXB for using the namespaces used in the XML document.
     */
    private static final class Event extends TransformedEvent.Start {
        /** Wraps the given event with potentially different name, namespaces and attributes. */
        Event(StartElement event, QName name, List<Namespace> namespaces, List<Attribute> attributes, TransformVersion version) {
            super(event, name, namespaces, attributes, version);
        }

        /**
         * Gets the URI used in the XML document for the given prefix used in JAXB annotations.
         * At marshalling time, events are created by JAXB using namespaces used in JAXB annotations.
         * {@link TransformingWriter} wraps those events for converting those namespaces to the ones used
         * in the XML document.
         *
         * <div class="note"><b>Example:</b> the {@code "cit"} prefix from ISO 19115-3:2016 standard
         * represents the {@code "http://standards.iso.org/iso/19115/-3/mdb/1.0"} namespace, which is
         * mapped to {@code "http://www.isotc211.org/2005/gmd"} in the legacy ISO 19139:2007 standard.
         * That later URI is returned.</div>
         */
        @Override
        public String getNamespaceURI(final String prefix) {
            return version.exportNS(event.getNamespaceURI(prefix));
        }

        /**
         * Returns a context mapping prefixes used in JAXB annotations to namespaces used in XML document.
         * The {@link TransformingNamespaces#getNamespaceURI(String)} method in that context shall do the same
         * work than {@link #getNamespaceURI(String)} in this event.
         *
         * @see TransformingNamespaces#getNamespaceURI(String)
         */
        @Override
        public NamespaceContext getNamespaceContext() {
            return TransformingNamespaces.asXML(event.getNamespaceContext(), version);
        }
    }

    /**
     * Writes any cached events to the underlying output mechanism.
     */
    @Override
    public void flush() throws XMLStreamException {
        writeDeferred(null);
        out.flush();
    }

    /**
     * Frees any resources associated with this writer.
     */
    @Override
    public void close() throws XMLStreamException {
        uniqueNamespaces.clear();
        super.close();
        out.close();
    }
}
