# SaxWriterImpl.java

    /*
    ** Module   : SaxWriterImpl
    ** Abstract : SAX writer specific features implementation.
    **
    ** Copyright (c) 2013-2025, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- ---------------------------------Description----------------------------------
    ** 001 EVL 20130208 Created initial version. Implementation is limited to the stubs to get the
    **                  converted java code compiled.
    ** 002 CA  20130221 This resource doesn't have NAME attribute support.
    ** 003 EVL 20130320 Spelling fixes for comments.
    ** 004 EVK 20131001 Implement methods and class logic.
    ** 005 EVK 20140113 Added method resourceDelete to properly remove the object.
    ** 006 OM  20160129 Fixed ClassCastException in SET-OUTPUT-DESTINATION.
    ** 007 ECF 20160419 Fixed NPE in writeDataElement and writeEmptyElement.
    ** 008 IAS 20160707 Fixed the behavior to be more consistent with 4GL SAX-WRITER one.
    ** 009 CA  20211126 Fixed performance when writing a XML via FileOutputStreamWrapper.
    **     EVL 20221017 Added namespace repair option set.
    ** 010 CA  20230116 Avoid using handle.unwrap, handle.getReference or other BDT usage from within FWD runtime.
    ** 011 GBB 20230512 Logging methods replaced by CentralLogger/ConversionStatus.
    ** 012 AS  20250903 Honor the fragment attribute of the writer.
    ** 013 CA  20250516 Fixed issues with XML namespaces - these need to be scoped for each XML element, and
    **                  ensure that when an element is written, it uses the prefix (if it exists).
    ** 014 CA  20250526 Namespace URIs and prefixes are looked up in all scopes, not just current scope.
    */
    /*
    ** This program is free software: you can redistribute it and/or modify
    ** it under the terms of the GNU Affero General Public License as
    ** published by the Free Software Foundation, either version 3 of the
    ** License, or (at your option) any later version.
    **
    ** This program is distributed in the hope that it will be useful,
    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    ** GNU Affero General Public License for more details.
    **
    ** You may find a copy of the GNU Affero GPL version 3 at the following
    ** location: https://www.gnu.org/licenses/agpl-3.0.en.html
    **
    ** Additional terms under GNU Affero GPL version 3 section 7:
    **
    **   Under Section 7 of the GNU Affero GPL version 3, the following additional
    **   terms apply to the works covered under the License.  These additional terms
    **   are non-permissive additional terms allowed under Section 7 of the GNU
    **   Affero GPL version 3 and may not be removed by you.
    **
    **   0. Attribution Requirement.
    **
    **     You must preserve all legal notices or author attributions in the covered
    **     work or Appropriate Legal Notices displayed by works containing the covered
    **     work.  You may not remove from the covered work any author or developer
    **     credit already included within the covered work.
    **
    **   1. No License To Use Trademarks.
    **
    **     This license does not grant any license or rights to use the trademarks
    **     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
    **     of Golden Code Development Corporation. You are not authorized to use the
    **     name Golden Code, FWD, or the names of any author or contributor, for
    **     publicity purposes without written authorization.
    **
    **   2. No Misrepresentation of Affiliation.
    **
    **     You may not represent yourself as Golden Code Development Corporation or FWD.
    **
    **     You may not represent yourself for publicity purposes as associated with
    **     Golden Code Development Corporation, FWD, or any author or contributor to
    **     the covered work, without written authorization.
    **
    **   3. No Misrepresentation of Source or Origin.
    **
    **     You may not represent the covered work as solely your work.  All modified
    **     versions of the covered work must be marked in a reasonable way to make it
    **     clear that the modified work is not originating from Golden Code Development
    **     Corporation or FWD.  All modified versions must contain the notices of
    **     attribution required in this license.
    */

    package com.goldencode.p2j.xml;

    import java.io.*;
    import java.util.*;
    import java.util.concurrent.atomic.*;
    import java.util.function.*;
    import java.util.logging.*;

    import javax.xml.namespace.*;
    import javax.xml.stream.*;
    import javax.xml.transform.*;
    import javax.xml.transform.dom.*;
    import javax.xml.transform.stream.*;

    import com.goldencode.p2j.util.logging.*;
    import org.codehaus.stax2.*;
    import org.w3c.dom.*;
    import org.xml.sax.*;

    import com.ctc.wstx.api.*;
    import com.ctc.wstx.stax.*;
    import com.goldencode.p2j.util.*;
    import com.goldencode.p2j.util.ErrorManager;
    import com.goldencode.p2j.util.Text;

    import javanet.staxutils.*;

    /**
     * Implementation SAX-Writer specific features of the SAX objects.
     */
    public class SaxWriterImpl
    extends SaxEntityImpl
    implements SaxWriter
    {
       /** default version of XML */
       private static final String DEFAULT_XML_VERSION = "1.0";

       /** Anonymous log instance. */
       private static final CentralLogger LOG = CentralLogger.get(SaxWriterImpl.class.getName());

       /** Current status of SAX-Writer */
       private WriteStatus writeStatus = WriteStatus.SAX_WRITE_IDLE;

       /** Current output source of SAX-Writer */
       private OutputStream outputWrapper = null;

       /** encoding of SAX-Writer */
       private String encoding = "";

       /** version of xml */
       private String version = DEFAULT_XML_VERSION;

       /** formatted attribute */
       private boolean formatted = false;

       /** strict attribute. */
       private boolean strict = true;

       /** fragment attribute. */
       private boolean fragment = false;

       /** standalone attribute. */
       private Boolean standalone = null;

       /** XML stream cursor writer.*/
       private XMLStreamWriter writer = null;

       /** Track the namespaces for each element. */
       private ScopedNamespaceContext nscontext = null;

       /**
        * Default constructor.
        */
       public SaxWriterImpl()
       {
          // no-op
       }

       /**
        * Gets the value of the encoding attribute for the given SAX-Writer object.
        *
        * @return   The character value of the encoding attribute.
        */
       @Override
       public character getEncoding()
       {
          return new character(encoding);
       }

       /**
        * Sets the new value of the encoding attribute for the given SAX-Writer object.
        *
        * @param    encoding
        *           The encoding value to be set for the given writer.
        */
       @Override
       public void setEncoding(String encoding)
       {
          setEncoding(new character(encoding));
       }

       /**
        * Sets the new value of the encoding attribute for the given SAX-Writer object.
        *
        * @param    encoding
        *           The encoding value to be set for the given writer.
        */
       @Override
       public void setEncoding(character encoding)
       {
          if (encoding.isUnknown())
          {
             invalidArgumentAssignError("ENCODING");
             return;
          }

          if (!WriteStatus.nonWritableStatuses.contains(writeStatus))
          {
             invalidStatusAttributeError("ENCODING", writeStatus);
             return;
          }

          this.encoding = encoding.toStringMessage();
       }

       /**
        * Gets the value of the formatted attribute for the given SAX-Writer object. Formatted means
        * extra space or carrage returns should be added to preserve the hierarchical view of the
        * document.
        *
        * @return   The <code>true</code> in case of formatted <code>false</code> otherwise.
        */
       @Override
       public logical getFormatted()
       {
          return new logical(formatted);
       }

       /**
        * Sets the value of the formatted attribute for the given SAX-Writer object. Formatted means
        * extra space or carriage returns should be added to preserve the hierarchical view of the
        * document.
        *
        * @param    isFormatted
        *           The <code>true</code> in case of formatted <code>false</code> otherwise.
        */
       @Override
       public void setFormatted(logical isFormatted)
       {
          if (!WriteStatus.nonWritableStatuses.contains(writeStatus))
          {
             invalidStatusAttributeError("FORMATTED", writeStatus);
             return;
          }

          formatted = isFormatted.booleanValue();
       }

       /**
        * Sets the value of the formatted attribute for the given SAX-Writer object. Formatted means
        * extra space or carrage returns should be added to preserve the hierarchical view of the
        * document.
        *
        * @param    isFormatted
        *           The <code>true</code> in case of formatted <code>false</code> otherwise.
        */
       @Override
       public void setFormatted(boolean isFormatted)
       {
          setFormatted(new logical(isFormatted));
       }

       /**
        * Gets the value of the strict attribute for the given SAX-Writer object. Strict means
        * SAX-Writer should make well formed XML document. The default is true.
        *
        * @return   The <code>true</code> in case of strict <code>false</code> otherwise.
        */
       @Override
       public logical getStrict()
       {
          return new logical(strict);
       }

       /**
        * Sets the value of the strict attribute for the given SAX-Writer object. Strict means
        * SAX-Writer should make well formed XML document. The default is true.
        *
        * @param    isStrict
        *           The <code>true</code> in case of strict <code>false</code> otherwise.
        */
       @Override
       public void setStrict(logical isStrict)
       {
          if (!WriteStatus.nonWritableStatuses.contains(writeStatus))
          {
             invalidStatusAttributeError("STRICT", writeStatus);
             return;
          }

          strict = isStrict.booleanValue();
       }

       /**
        * Sets the value of the strict attribute for the given SAX-Writer object. Strict means
        * SAX-Writer should make well formed XML document. The default is true.
        *
        * @param    isStrict
        *           The <code>true</code> in case of strict <code>false</code> otherwise.
        */
       @Override
       public void setStrict(boolean isStrict)
       {
          setStrict(new logical(isStrict));
       }

       /**
        * Gets the value of the fragment attribute for the given SAX-Writer object. Fragment means
        * SAX-Writer output is part of the document or full.
        *
        * @return   The <code>true</code> in case of fragment <code>false</code> for full document.
        */
       @Override
       public logical getFragment()
       {
          return new logical(fragment);
       }

       /**
        * Sets the value of the fragment attribute for the given SAX-Writer object. Fragment means
        * SAX-Writer output is part of the document or full.
        *
        * @param    isFragment
        *           The <code>true</code> in case of fragment <code>false</code> for full document.
        */
       @Override
       public void setFragment(logical isFragment)
       {
          if (!WriteStatus.nonWritableStatuses.contains(writeStatus))
          {
             invalidStatusAttributeError("FRAGMENT", writeStatus);
             return;
          }

          fragment = isFragment.booleanValue();
       }

       /**
        * Sets the value of the fragment attribute for the given SAX-Writer object. Fragment means
        * SAX-Writer output is part of the document or full.
        *
        * @param    isFragment
        *           The <code>true</code> in case of fragment <code>false</code> for full document.
        */
       @Override
       public void setFragment(boolean isFragment)
       {
          setFragment(new logical(isFragment));
       }

       /**
        * Gets the value of the standalone attribute for the given SAX-Writer object.
        *
        * @return   The character value of the standalone attribute.
        */
       @Override
       public logical getStandalone()
       {
          return new logical(standalone);
       }

       /**
        * Sets the value of the standalone attribute for the given SAX-Writer object.
        *
        * @param    isStandalone
        *           The <code>true</code> in case of standalone <code>false</code> otherwise.
        */
       @Override
       public void setStandalone(logical isStandalone)
       {
          if (!WriteStatus.nonWritableStatuses.contains(writeStatus))
          {
             invalidStatusAttributeError("STANDALONE", writeStatus);
             return;
          }

          standalone = isStandalone.toJavaType();
       }

       /**
        * Sets the value of the standalone attribute for the given SAX-Writer object.
        *
        * @param    isStandalone
        *           The <code>true</code> in case of standalone <code>false</code> otherwise.
        */
       @Override
       public void setStandalone(boolean isStandalone)
       {
          setStandalone(new logical(isStandalone));
       }

       /**
        * Gets the value of the version attribute for the given SAX-Writer object.
        *
        * @return   The character value of the version attribute.
        */
       @Override
       public character getVersion()
       {
          return new character(version);
       }

       /**
        * Sets the new value of the version attribute for the given SAX-Writer object.
        *
        * @param    version
        *           The version value to be set for the given writer.
        */
       @Override
       public void setVersion(String version)
       {
          setVersion(new character(version));
       }

       /**
        * Sets the new value of the version attribute for the given SAX-Writer object.
        *
        * @param    version
        *           The version value to be set for the given writer.
        */
       @Override
       public void setVersion(character version)
       {
          if (version.isUnknown())
          {
             invalidArgumentAssignError("VERSION");
             return;
          }

          if (!WriteStatus.nonWritableStatuses.contains(writeStatus))
          {
             invalidStatusAttributeError("VERSION", writeStatus);
             return;
          }

          this.version = version.toStringMessage();
       }

       /**
        * Gets the value of the write-status attribute for the given SAX-Writer object. This is one
        * of the SAX_WRITE_* constants defined by the {@link SaxWriter} interface.
        * <p>
        * Documentation states that the type of this attribute is character, but this is incorrect.
        * The attribute's real type is integer, same as PARSE-STATUS for the SAX-Reader object.
        *
        * @return   The integer value of the write-status attribute.
        */
       @Override
       public integer getWriteStatus()
       {
          return new integer(writeStatus.getStatus());
       }

       /**
        * Adds namespace declaration to a tag in a XML document associated with SAX-Writer object.
        *
        * @param    uri
        *           The URI namespace to add.
        * @param    prefix
        *           The prefix of the namespace to add.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical declareNamespace(Text uri, Text prefix)
       {
          if (!WriteStatus.writableBodyStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("DECLARE-NAMESPACE", writeStatus);
             return new logical(false);
          }

          String prefixStr = prefix.isUnknown() ? "" : prefix.toStringMessage();
          try
          {
             writer.writeNamespace(prefixStr, uri.toStringMessage());
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("DECLARE-NAMESPACE");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Adds namespace declaration to a tag in a XML document associated with SAX-Writer object.
        *
        * @param    uri
        *           The URI namespace to add.
        * @param    prefix
        *           The prefix of the namespace to add.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical declareNamespace(String uri, Text prefix)
       {
          return declareNamespace(new character(uri), prefix);
       }

       /**
        * Adds namespace declaration to a tag in a XML document associated with SAX-Writer object.
        *
        * @param    uri
        *           The URI namespace to add.
        * @param    prefix
        *           The prefix of the namespace to add.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical declareNamespace(Text uri, String prefix)
       {
          return declareNamespace(uri, new character(prefix));
       }

       /**
        * Adds namespace declaration to a tag in a XML document associated with SAX-Writer object.
        *
        * @param    uri
        *           The URI namespace to add.
        * @param    prefix
        *           The prefix of the namespace to add.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical declareNamespace(String uri, String prefix)
       {
          return declareNamespace(new character(uri), new character(prefix));
       }

       /**
        * Adds namespace declaration to a tag in a XML document associated with SAX-Writer object.
        *
        * @param    uri
        *           The URI namespace to add.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical declareNamespace(String uri)
       {
          return declareNamespace(new character(uri), new character());
       }

       /**
        * Adds namespace declaration to a tag in a XML document associated with SAX-Writer object.
        *
        * @param    uri
        *           The URI namespace to add.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical declareNamespace(Text uri)
       {
          return declareNamespace(uri, new character());
       }

       /**
        * Closes the XML document associated with SAX-Writer object.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical endDocument()
       {
          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("END-DOCUMENT", writeStatus);
             return new logical(false);
          }

          try
          {
             writer.writeEndDocument();
             writer.close();
             writeStatus = WriteStatus.SAX_WRITE_COMPLETE;
             outputWrapper.close();
             nscontext.endElement();
          }
          catch (XMLStreamException | IOException ignored)
          {
             writerOutputError("END-DOCUMENT");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Ends an XML node of the given name in a XML document associated with SAX-Writer object.
        *
        * @param    name
        *           The name of the node to end.
        * @param    uri
        *           The URI namespace of the node to end.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical endElement(Text name, Text uri)
       {
          if (!BaseDataType.elementsOfType(character.class, uri, name))
          {
             invalidArgumentError("END-ELEMENT");
             return new logical(false);
          }

          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("END-ELEMENT", writeStatus);
             return new logical(false);
          }

          try
          {
             writer.writeEndElement();
             nscontext.endElement();
             writeStatus = WriteStatus.SAX_WRITE_ELEMENT;
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("END-ELEMENT");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Ends an XML node of the given name in a XML document associated with SAX-Writer object.
        *
        * @param    name
        *           The name of the node to end.
        * @param    uri
        *           The URI namespace of the node to end.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical endElement(String name, Text uri)
       {
          return endElement(new character(name), uri);
       }

       /**
        * Ends an XML node of the given name in a XML document associated with SAX-Writer object.
        *
        * @param    name
        *           The name of the node to end.
        * @param    uri
        *           The URI namespace of the node to end.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical endElement(Text name, String uri)
       {
          return endElement(name, new character(uri));
       }

       /**
        * Ends an XML node of the given name in a XML document associated with SAX-Writer object.
        *
        * @param    name
        *           The name of the node to end.
        * @param    uri
        *           The URI namespace of the node to end.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical endElement(String name, String uri)
       {
          return endElement(new character(name), new character(uri));
       }

       /**
        * Ends an XML node of the given name in a XML document associated with SAX-Writer object.
        *
        * @param    name
        *           The name of the node to end.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical endElement(String name)
       {
          return endElement(new character(name), new character());
       }

       /**
        * Ends an XML node of the given name in a XML document associated with SAX-Writer object.
        *
        * @param    name
        *           The name of the node to end.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical endElement(Text name)
       {
          return endElement(name, new character());
       }

       /**
        * Specifies the output destination of the XML document to be created by a SAX-Writer object.
        *
        * @param    mode
        *           The type of the destination to write to. Can be 'FILE', 'STREAM', 'MEMPTR',
        *           'STREAM-HANDLE' or 'LONGCHAR'.
        * @param    destination
        *           The appropriate object to write.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical setOutputDestination(String mode, Object destination)
       {
          return setOutputDestination(new character(mode), destination);
       }

       /**
        * Specifies the output destination of the XML document to be created by a SAX-Writer object.
        *
        * @param    mode
        *           The type of the destination to write to. Can be 'FILE', 'STREAM', 'MEMPTR',
        *           'STREAM-HANDLE' or 'LONGCHAR'.
        * @param    destination
        *           The appropriate object to write.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical setOutputDestination(character mode, Object destination)
       {
          if (!WriteStatus.nonWritableStatuses.contains(writeStatus))
          {
             invalidStatusAttributeError("SET-OUTPUT-DESTINATION", writeStatus);
             return new logical(false);
          }

          final String writeMode;
          if (mode.isUnknown())
          {
             writeMode = "file";
          }
          else
          {
             writeMode = mode.getValue();
          }

          if ("file".equalsIgnoreCase(writeMode))
          {
             String fileName = null;
             if (destination instanceof String)
             {
                fileName = (String) destination;
             }
             else if (destination instanceof Text)
             {
                fileName = ((Text) destination).getValue();
             }
             else
             {
                String msg = "The SET-OUTPUT-DESTINATION attribute on the SAX-WRITER widget has " +
                             "invalid arguments";
                ErrorManager.recordOrShowError(4065, msg, false, true);
                return new logical(false);
             }

             outputWrapper = new FileOutputStreamWrapper(fileName);
          }
          else if ("stream".equalsIgnoreCase(writeMode))
          {
             LOG.warning("Stream is not supported");
             return new logical(false);
          }
          else if ("memptr".equalsIgnoreCase(writeMode))
          {
             outputWrapper = new MemptrOutputStream((memptr) destination);
          }
          else if ("stream-handle".equalsIgnoreCase(writeMode))
          {
             LOG.warning("Stream-handle is not supported");
             return new logical(false);
          }
          else if ("longchar".equalsIgnoreCase(writeMode))
          {
             outputWrapper = new LongcharOutputStream((longchar) destination);
          }
          else
          {
             invalidReadWriteModeError("SET-OUTPUT-DESTINATION");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Creates the XML document with the prolog information.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startDocument()
       {
          if (!WriteStatus.nonWritableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("START-DOCUMENT", writeStatus);
             return new logical(false);
          }

          if (outputWrapper == null)
          {
             String msg = "START-DOCUMENT was unable to open the output destination. " +
                          "No output destination was specified";
             ErrorManager.recordOrShowError(14610, msg, false, false, false);
          }

          XMLOutputFactory2 output = (XMLOutputFactory2) XMLOutputFactory2.newFactory();
          output.configureForSpeed();
          output.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, false);
          output.setProperty(WstxOutputProperties.P_AUTOMATIC_END_ELEMENTS, false);
          output.setProperty(WstxOutputFactory.P_AUTOMATIC_EMPTY_ELEMENTS, false);
          output.setProperty("javax.xml.stream.isRepairingNamespaces", true);

          try
          {
             writer = output.createXMLStreamWriter(outputWrapper);
             if (formatted)
             {
                writer = new IndentingXMLStreamWriter(writer)
                {
                   int depth = 0;

                   @Override
                   protected void beforeEndElement()
                   {
                      if (depth == 1 && writeStatus == WriteStatus.SAX_WRITE_TAG)
                      {
                         writeLn();
                      }
                      super.beforeEndElement();
                   }

                   @Override
                   protected void afterEndElement()
                   {
                      super.afterEndElement();
                      if (--depth == 0)
                      {
                         writeLn();
                      }
                   }

                   @Override
                   protected void afterStartElement()
                   {
                      super.afterStartElement();
                      depth++;
                   }

                   protected void writeLn()
                   {
                      try
                      {
                         writeNewLine(0);
                      }
                      catch (XMLStreamException ignore)
                      {
                      }
                   }
                };
             }

             nscontext = new ScopedNamespaceContext();
             nscontext.startElement();
             writer.setNamespaceContext(nscontext);
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("START-DOCUMENT");
             return new logical(false);
          }

          if (!fragment)
          {
             try
             {
                writeXMLDeclaration(writer, version, encoding, standalone == null ? null : standalone);
             }
             catch (XMLStreamException ignored) {
                writerOutputError("START-DOCUMENT");
                return new logical(false);
             }
          }
          writeStatus = WriteStatus.SAX_WRITE_BEGIN;

          return new logical(true);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(Text name)
       {
          return startElement(name, new character(), null);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(String name)
       {
          return startElement(new character(name), new character(), null);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(Text name, handle handle)
       {
          return startElement(name, new character(), handle);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(String name, handle handle)
       {
          return startElement(new character(name), new character(), handle);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(Text name, Text uri)
       {
          return startElement(new character(name), uri, null);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(String name, Text uri)
       {
          return startElement(new character(name), uri, null);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(Text name, String uri)
       {
          return startElement(name, new character(uri), null);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(String name, String uri)
       {
          return startElement(new character(name), new character(uri), null);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(String name, Text uri, handle handle)
       {
          return startElement(new character(name), uri, handle);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(Text name, String uri, handle handle)
       {
          return startElement(name, new character(uri), handle);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(String name, String uri, handle handle)
       {
          return startElement(new character(name), new character(uri), handle);
       }

       /**
        * Adding the single attribute to the start tag in the XML document if applied for SAX writer
        * object. For SAX attributes object inserts attribute and its name into SAX attributes object.
        *
        * @param    name
        *           The attribute name to insert.
        * @param    value
        *           The attribute value to insert.
        * @param    uri
        *           The URI of the attribute to insert or '?' for unknown value.
        *
        * @return The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical insertAttribute(Text name, Text value, Text uri)
       {
          if (!BaseDataType.elementsOfType(character.class, uri, name, value))
          {
             invalidArgumentError("INSERT-ATTRIBUTE");
             return new logical(false);
          }

          if (name.isUnknown() || value.isUnknown())
          {
             invalidArgumentError("INSERT-ATTRIBUTE");
             return new logical(false);
          }

          try
          {
             if (uri.isUnknown())
             {
                String attr = name.toStringMessage();
                if (attr.startsWith("xmlns:"))
                {
                   String xmlns = attr.substring(attr.indexOf(':') + 1);
                   nscontext.setPrefix(xmlns, value.toStringMessage());
                }
                writer.writeAttribute(attr, value.toStringMessage());
             }
             else
             {
                writer.writeAttribute(uri.toStringMessage(),
                                       name.toStringMessage(),
                                       value.toStringMessage());
             }
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("INSERT-ATTRIBUTE");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Starts the XML node according to the specified name, namespace URI and handle of the SAX
        * attribute object.
        *
        * @param    name
        *           The name of the element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    attr
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical startElement(Text name, Text uri, handle attr)
       {
          if (!BaseDataType.elementsOfType(character.class, uri, name))
          {
             invalidArgumentError("START-ELEMENT");
             return new logical(false);
          }

          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("START-ELEMENT", writeStatus);
             return new logical(false);
          }

          if (name.isUnknown())
          {
             invalidArgumentError("START-ELEMENT");
             return new logical(false);
          }
          if (attr != null && !attr.isUnknown() && !handle.isHandleTypeOf(attr, SaxAttributes.class))
          {
             invalidArgumentError("START-ELEMENT");
             return new logical(false);
          }
          try
          {
             String uriStr = uri.isUnknown() ? "" : uri.toStringMessage();
             String prefix = nscontext.getPrefix(uriStr);
             if (prefix == null)
             {
                writer.setDefaultNamespace(uriStr);
                writer.writeStartElement(uriStr, name.toStringMessage());
             }
             else
             {
                writer.writeStartElement(prefix, name.toStringMessage(), uriStr);
             }
             writeStatus = WriteStatus.SAX_WRITE_TAG;
             nscontext.startElement();

             if (attr == null || attr.isUnknown())
             {
                return new logical(true);
             }

             Attributes attributes = ((SaxAttributesImpl) attr.getResource()).getAttributes();
             for (int i = 0; i < attributes.getLength(); i++)
             {
                logical res = insertAttribute(attributes.getLocalName(i), attributes.getValue(i));
                if (!res.booleanValue())
                {
                   return res;
                }
             }
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-ELEMENT");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Adds CDATA block to the XML document crating by SAX-Writer object.
        *
        * @param    cdataBlock
        *           The data to be written with CDATA block.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeCdata(String cdataBlock)
       {
          return writeCdata(new character(cdataBlock));
       }

       /**
        * Adds CDATA block to the XML document crating by SAX-Writer object.
        *
        * @param    cdataBlock
        *           The data to be written with CDATA block.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeCdata(Text cdataBlock)
       {
          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("WRITE-CDATA", writeStatus);
             return new logical(false);
          }

          if (cdataBlock.isUnknown())
          {
             invalidArgumentError("WRITE-CDATA");
             return new logical(false);
          }

          try
          {
             writer.writeCData(cdataBlock.toStringMessage());
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-CDATA");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Adds character data to the XML document crating by SAX-Writer object.
        *
        * @param    chardata
        *           The character or longchar data to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeCharacters(String chardata)
       {
          return writeCharacters(new character(chardata));
       }

       /**
        * Adds character data to the XML document crating by SAX-Writer object.
        *
        * @param    chardata
        *           The character or longchar data to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeCharacters(Text chardata)
       {
          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("WRITE-CHARACTERS", writeStatus);
             return new logical(false);
          }

          if (chardata.isUnknown())
          {
             invalidArgumentError("WRITE-CHARACTERS");
             return new logical(false);
          }

          try
          {
             writer.writeCharacters(chardata.toStringMessage());
             writeStatus = WriteStatus.SAX_WRITE_CONTENT;
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-CHARACTERS");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, Text chardata)
       {
          return writeDataElement(name, chardata, new character(), null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, Text chardata)
       {
          return writeDataElement(new character(name), chardata, new character(), null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, String chardata)
       {
          return writeDataElement(name, new character(chardata), new character(), null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, String chardata)
       {
          return writeDataElement(new character(name), new character(chardata), new character(),
                                  null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, Text chardata, Text uri)
       {
          return writeDataElement(name, chardata, uri, null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, Text chardata, Text uri)
       {
          return writeDataElement(new character(name), chardata, uri, null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, String chardata, Text uri)
       {
          return writeDataElement(name, new character(chardata), uri, null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, String chardata, Text uri)
       {
          return writeDataElement(new character(name), new character(chardata), uri, null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, Text chardata, String uri)
       {
          return writeDataElement(name, chardata, new character(uri), null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, Text chardata, String uri)
       {
          return writeDataElement(new character(name), chardata, new character(uri), null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, String chardata, String uri)
       {
          return writeDataElement(name, new character(chardata), new character(uri), null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, String chardata, String uri)
       {
          return writeDataElement(new character(name), new character(chardata),
                                  new character(uri), null);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, Text chardata, handle handle)
       {
          return writeDataElement(name, chardata, new character(), handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, Text chardata, handle handle)
       {
          return writeDataElement(new character(name), chardata, new character(), handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, String chardata, handle handle)
       {
          return writeDataElement(name, new character(chardata), new character(), handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, String chardata, handle handle)
       {
          return writeDataElement(new character(name), new character(chardata), new character(),
                                  handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, Text chardata, Text uri, handle handle)
       {
          return writeDataElement(new character(name), chardata, uri, handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, String chardata, Text uri, handle handle)
       {
          return writeDataElement(name, new character(chardata), uri, handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, Text chardata, String uri, handle handle)
       {
          return writeDataElement(name, chardata, new character(uri), handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, String chardata, Text uri, handle handle)
       {
          return writeDataElement(new character(name), new character(chardata), uri, handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, Text chardata, String uri, handle handle)
       {
          return writeDataElement(new character(name), chardata, new character(uri), handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, String chardata, String uri, handle handle)
       {
          return writeDataElement(name, new character(chardata), new character(uri), handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    handle
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(String name, String chardata, String uri, handle handle)
       {
          return writeDataElement(new character(name), new character(chardata),
                                  new character(uri), handle);
       }

       /**
        * Creates complete XML node with a given SAX-Writer object.
        *
        * @param    name
        *           The name of the element.
        * @param    chardata
        *           The XML text to write for the given element.
        * @param    uri
        *           The namespace URI of the given element.
        * @param    attr
        *           The handle of the SAX-Attribute object to be added into XML document.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeDataElement(Text name, Text chardata, Text uri, handle attr)
       {
          if (!BaseDataType.elementsOfType(character.class, uri, name))
          {
             invalidArgumentError("WRITE-DATA-ELEMENT");
             return new logical(false);
          }

          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("WRITE-DATA-ELEMENT", writeStatus);
             return new logical(false);
          }

          if (name.isUnknown())
          {
             invalidArgumentError("WRITE-DATA-ELEMENT");
             return new logical(false);
          }

          if (attr != null && !attr.isUnknown() && !handle.isHandleTypeOf(attr, SaxAttributes.class))
          {
             invalidArgumentError("WRITE-DATA-ELEMENT");
             return new logical(false);
          }

          try
          {
             String uriStr = uri.isUnknown() ? "" : uri.toStringMessage();
             String prefix = nscontext.getPrefix(uriStr);
             if (prefix != null)
             {
                writer.writeStartElement(prefix, name.toStringMessage(), uriStr);
             }
             else
             {
                // for this node, ensure the uri is the default namespace, so it will not use a prefix
                writer.setDefaultNamespace(uriStr);
                writer.writeStartElement(uriStr, name.toStringMessage());
                writer.setDefaultNamespace(null);
             }
             writeStatus = WriteStatus.SAX_WRITE_TAG;

             if (attr != null)
             {
                Attributes attributes = ((SaxAttributesImpl) attr.getResource()).getAttributes();
                for(int i = 0; i < attributes.getLength(); i++)
                {
                   logical res = insertAttribute(attributes.getLocalName(i), attributes.getValue(i));
                   if (!res.booleanValue())
                   {
                      return res;
                   }
                }
             }

             if (!chardata.isUnknown())
             {
                writer.writeCharacters(chardata.toStringMessage());
             }

             writer.writeEndElement();
             writeStatus = WriteStatus.SAX_WRITE_ELEMENT;
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-EMPTY-ELEMENT");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Adds character data to the XML document crating by SAX-Writer object.
        *
        * @param    chardata
        *           The character or longchar data to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeFragment(String chardata)
       {
          return writeFragment(new character(chardata));
       }

       /**
        * Adds character data to the XML document crating by SAX-Writer object.
        *
        * @param    chardata
        *           The character or longchar data to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeFragment(Text chardata)
       {
          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("WRITE-FRAGMENT", writeStatus);
             return new logical(false);
          }

          if (chardata.isUnknown())
          {
             invalidArgumentError("WRITE-FRAGMENT");
             return new logical(false);
          }

          String content = chardata.toStringMessage();

          return writeCharacterData(content);
       }

       /**
        * Adds character data to the XML document crating by SAX-Writer object.
        *
        * @param    content
        *           string to write.
        *
        * @return   {@code true} if success, {@code false} otherwise.
        */
       private logical writeCharacterData(String content)
       {
          try
          {
             writer.writeCharacters(content);
             writeStatus = WriteStatus.SAX_WRITE_CONTENT;
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-FRAGMENT");
             return new logical(false);
          }
          return new logical(true);
       }

       /**
        * Adds character data to the XML document crating by SAX-Writer object.
        *
        * @param    xhandle
        *           The valid X-Nodereference handle containing XML text.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeFragment(handle xhandle)
       {
          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("WRITE-FRAGMENT", writeStatus);
             return new logical(false);
          }

          if (!XEntityImpl.isXNodeHandle(xhandle) || !XEntityImpl.isXNodeHandleInitialized(xhandle))
          {
             invalidArgumentError("WRITE-FRAGMENT");
             return new logical(false);
          }

          Node node = ((XEntityImpl) xhandle.get()).getNode();

          String nodeXML;
          try
          {
             nodeXML = serializeNodeToString(node);
          }
          catch (TransformerException ignored)
          {
             invalidArgumentError("WRITE-FRAGMENT");
             return new logical(false);
          }

          return writeCharacterData(nodeXML);
       }

       /**
        * Closes the open stream and resets the SAX-Writer object to the default state.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical reset()
       {
          if (outputWrapper != null)
          {
             try
             {
                outputWrapper.close();
             }
             catch (IOException ignored)
             {
                // no-op
             }
          }
          writeStatus = WriteStatus.SAX_WRITE_IDLE;
          return new logical(true);
       }

       /**
        * Adds comment to the XML document crating by SAX-Writer object.
        *
        * @param    comment
        *           The character or longchar text comment to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeComment(String comment)
       {
          return writeComment(new character(comment));
       }

       /**
        * Adds comment to the XML document crating by SAX-Writer object.
        *
        * @param    comment
        *           The character or longchar text comment to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeComment(Text comment)
       {
          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("WRITE-COMMENT", writeStatus);
             return new logical(false);
          }

          if (comment.isUnknown())
          {
             invalidArgumentError("WRITE-COMMENT");
             return new logical(false);
          }

          try
          {
             writer.writeComment(comment.toStringMessage());
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-COMMENT");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(Text name)
       {
          return writeEmptyElement(name, new character(), null);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(String name)
       {
          return writeEmptyElement(new character(name), new character(), null);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    uri
        *           The character or longchar element URI to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(Text name, Text uri)
       {
          return writeEmptyElement(name, uri, null);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    uri
        *           The character or longchar element URI to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(String name, Text uri)
       {
          return writeEmptyElement(new character(name), uri, null);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    uri
        *           The character or longchar element URI to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(Text name, String uri)
       {
          return writeEmptyElement(name, new character(uri), null);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    uri
        *           The character or longchar element URI to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(String name, String uri)
       {
          return writeEmptyElement(new character(name), new character(uri), null);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    attr
        *           The handle of the SAX-Attributes object to be used.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(Text name, handle attr)
       {
          return writeEmptyElement(name, new character(), attr);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    attr
        *           The handle of the SAX-Attributes object to be used.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(String name, handle attr)
       {
          return writeEmptyElement(new character(name), new character(), attr);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    uri
        *           The character or longchar element URI to be written.
        * @param    attr
        *           The handle of the SAX-Attributes object to be used.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(String name, Text uri, handle attr)
       {
          return writeEmptyElement(new character(name), uri, attr);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    uri
        *           The character or longchar element URI to be written.
        * @param    attr
        *           The handle of the SAX-Attributes object to be used.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(Text name, String uri, handle attr)
       {
          return writeEmptyElement(name, new character(uri), attr);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    uri
        *           The character or longchar element URI to be written.
        * @param    attr
        *           The handle of the SAX-Attributes object to be used.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(String name, String uri, handle attr)
       {
          return writeEmptyElement(new character(name), new character(uri), attr);
       }

       /**
        * Creates an empty node in a given SAX-Writer object.
        *
        * @param    name
        *           The character or longchar element name to be written.
        * @param    uri
        *           The character or longchar element URI to be written.
        * @param    attr
        *           The handle of the SAX-Attributes object to be used.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEmptyElement(Text name, Text uri, handle attr)
       {
          if (!BaseDataType.elementsOfType(character.class, uri, name))
          {
             invalidArgumentError("WRITE-EMPTY-ELEMENT");
             return new logical(false);
          }

          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("WRITE-EMPTY-ELEMENT", writeStatus);
             return new logical(false);
          }

          if (name.isUnknown())
          {
             invalidArgumentError("WRITE-EMPTY-ELEMENT");
             return new logical(false);
          }

          if (attr != null && !attr.isUnknown() && !handle.isHandleTypeOf(attr, SaxAttributes.class))
          {
             invalidArgumentError("WRITE-EMPTY-ELEMENT");
             return new logical(false);
          }

          try
          {
             String uriStr = uri.isUnknown() ? null : uri.toStringMessage();

             writer.writeEmptyElement(uriStr, name.toStringMessage());
             writeStatus = WriteStatus.SAX_WRITE_TAG;

             if (attr != null)
             {
                Attributes attributes = ((SaxAttributesImpl) attr.getResource()).getAttributes();
                for (int i = 0; i < attributes.getLength(); i++)
                {
                   logical res = insertAttribute(attributes.getLocalName(i), attributes.getValue(i));
                   if (!res.booleanValue())
                   {
                      return res;
                   }
                }
             }
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-EMPTY-ELEMENT");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Adds an entity referenc to the XML document associated with given SAX-Writer object.
        *
        * @param    value
        *           The character or longchar value to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEntityRef(String value)
       {
          return writeEntityRef(new character(value));
       }

       /**
        * Adds an entity referenc to the XML document associated with given SAX-Writer object.
        *
        * @param    value
        *           The character or longchar value to be written.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeEntityRef(Text value)
       {
          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("WRITE-ENTITY-REF", writeStatus);
             return new logical(false);
          }

          if (value.isUnknown())
          {
             invalidArgumentError("WRITE-ENTITY-REF");
             return new logical(false);
          }

          try
          {
             writer.writeEntityRef(value.toStringMessage());
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-ENTITY-REF");
             return new logical(false);
          }
          return new logical(true);
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(Text name, Text systemId)
       {
          return writeExternalDtd(name, systemId, new character());
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(String name, Text systemId)
       {
          return writeExternalDtd(new character(name), systemId, new character());
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(Text name, String systemId)
       {
          return writeExternalDtd(name, new character(systemId), new character());
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(String name, String systemId)
       {
          return writeExternalDtd(new character(name), new character(systemId), new character());
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        * @param    publicId
        *           The character or longchar public ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(String name, Text systemId, Text publicId)
       {
          return writeExternalDtd(new character(name), systemId, publicId);
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        * @param    publicId
        *           The character or longchar public ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(Text name, String systemId, Text publicId)
       {
          return writeExternalDtd(name, new character(systemId), publicId);
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        * @param    publicId
        *           The character or longchar public ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(String name, String systemId, Text publicId)
       {
          return writeExternalDtd(new character(name), new character(systemId), publicId);
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        * @param    publicId
        *           The character or longchar public ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(Text name, Text systemId, String publicId)
       {
          return writeExternalDtd(name, systemId, new character(publicId));
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        * @param    publicId
        *           The character or longchar public ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(String name, Text systemId, String publicId)
       {
          return writeExternalDtd(new character(name), systemId, new character(publicId));
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        * @param    publicId
        *           The character or longchar public ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(Text name, String systemId, String publicId)
       {
          return writeExternalDtd(name, new character(systemId), new character(publicId));
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        * @param    publicId
        *           The character or longchar public ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(String name, String systemId, String publicId)
       {
          return writeExternalDtd(new character(name), new character(systemId),
                                  new character(publicId));
       }

       /**
        * Adds an external DTD reference to the XML document associated with a SAX-Writer object.
        *
        * @param    name
        *           The character or longchar name of the document root node.
        * @param    systemId
        *           The character or longchar system ID of the DTD.
        * @param    publicId
        *           The character or longchar public ID of the DTD.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeExternalDtd(Text name, Text systemId, Text publicId)
       {
          if (writeStatus != WriteStatus.SAX_WRITE_BEGIN)
          {
             invalidStatusMethodError("WRITE-EXTERNAL-DTD", writeStatus);
             return new logical(false);
          }

          if (name.isUnknown())
          {
             invalidArgumentError("WRITE-EXTERNAL-DTD");
             return new logical(false);
          }

          if (systemId.isUnknown())
          {
             invalidArgumentError("WRITE-EXTERNAL-DTD");
             return new logical(false);
          }

          StringBuilder xmlDeclarationBuilder = new StringBuilder();
          xmlDeclarationBuilder.append("<!DOCTYPE ");
          xmlDeclarationBuilder.append(name.toStringMessage());
          xmlDeclarationBuilder.append(' ');
          xmlDeclarationBuilder.append(systemId.toStringMessage());
          if (!publicId.isUnknown())
          {
             xmlDeclarationBuilder.append(" \"");
             xmlDeclarationBuilder.append(publicId.toStringMessage());
             xmlDeclarationBuilder.append('"');
          }
          xmlDeclarationBuilder.append(">\n");

          try
          {
             writer.writeDTD(xmlDeclarationBuilder.toString());
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-EXTERNAL-DTD");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Creates a processing instruction node in XML document for given SAX-Writer object.
        *
        * @param    target
        *           The character or longchar target of the processing instruction.
        * @param    data
        *           The character or longchar data associated with the processing instruction.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeProcessingInstruction(String target, Text data)
       {
          return writeProcessingInstruction(new character(target), data);
       }

       /**
        * Creates a processing instruction node in XML document for given SAX-Writer object.
        *
        * @param    target
        *           The character or longchar target of the processing instruction.
        * @param    data
        *           The character or longchar data associated with the processing instruction.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeProcessingInstruction(Text target, String data)
       {
          return writeProcessingInstruction(target, new character(data));
       }

       /**
        * Creates a processing instruction node in XML document for given SAX-Writer object.
        *
        * @param    target
        *           The character or longchar target of the processing instruction.
        * @param    data
        *           The character or longchar data associated with the processing instruction.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeProcessingInstruction(String target, String data)
       {
          return writeProcessingInstruction(new character(target), new character(data));
       }

       /**
        * Creates a processing instruction node in XML document for given SAX-Writer object.
        *
        * @param    target
        *           The character or longchar target of the processing instruction.
        * @param    data
        *           The character or longchar data associated with the processing instruction.
        *
        * @return   The <code>true</code> in case of success <code>false</code> otherwise.
        */
       @Override
       public logical writeProcessingInstruction(Text target, Text data)
       {
          if (!WriteStatus.writableStatuses.contains(writeStatus))
          {
             invalidStatusMethodError("WRITE-PROCESSING-INSTRUCTION", writeStatus);
             return new logical(false);
          }

          if (target.isUnknown())
          {
             invalidArgumentError("WRITE-PROCESSING-INSTRUCTION");
             return new logical(false);
          }

          if (data.isUnknown())
          {
             invalidArgumentError("WRITE-PROCESSING-INSTRUCTION");
             return new logical(false);
          }

          try
          {
             writer.writeProcessingInstruction(target.toStringMessage(), data.toStringMessage());
          }
          catch (XMLStreamException ignored)
          {
             writerOutputError("WRITE-PROCESSING-INSTRUCTION");
             return new logical(false);
          }

          return new logical(true);
       }

       /**
        * Check if this resource supports the NAME attribute.
        *
        * @return   Always <code>false</code>.
        */
       @Override
       protected boolean hasName()
       {
          return false;
       }

       /**
        * Delete the resource.
        *
        * @return   <code>true</code> if the resource was deleted.
        */
       @Override
       protected boolean resourceDelete()
       {
          if (writer != null)
          {
             try
             {
                writer.close();
             }
             catch (XMLStreamException e)
             {
                LOG.log(Level.SEVERE, "SaxWriterImpl", e);
             }
          }
          isValid = false;
          writer = null;
          nscontext = null;

          return true;
       }

       /**
        * This method is used to serialize Node from DOM to string.
        *
        * @param    node
        *           Node instance from DOM model.
        *
        * @return   Text representation of the node.
        *
        * @throws   TransformerFactoryConfigurationError
        *           If an error occurs writing the identifier.
        * @throws   TransformerException
        *           If an error occurs writing the identifier.
        */
       static String serializeNodeToString(Node node)
       throws TransformerFactoryConfigurationError,
              TransformerException
       {
          StreamResult xmlOutput = new StreamResult(new StringWriter());
          Transformer transformer = TransformerFactory.newInstance().newTransformer();
          transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
          transformer.transform(new DOMSource(node), xmlOutput);
          return xmlOutput.getWriter().toString();
       }

       /**
        * This method is used to write the XML document declaration at the beginning of an XML
        * document. This version is used when the standalone attribute is to be written as the
        * XMLStreamWriter provides no way for writing this attribute.
        *
        * @param    outputWriter
        *           XMLStreamWriter instance.
        * @param    xmlVersion
        *           Xml version which will specify in xml header.
        * @param    encodingName
        *           encoding which will specify in xml header.
        * @param    standalone
        *           standalone flag.
        *
        * @throws   XMLStreamException
        *           If an error occurs writing the identifier.
        */
       public static void writeXMLDeclaration(XMLStreamWriter outputWriter,
                                              String xmlVersion,
                                              String encodingName,
                                              Boolean standalone)
       throws XMLStreamException
       {
          if (xmlVersion == null || xmlVersion.trim().isEmpty())
          {
             xmlVersion = DEFAULT_XML_VERSION;
          }
          StringBuilder xmlDeclarationBuilder = new StringBuilder();
          xmlDeclarationBuilder.append("<?xml version=\"");
          xmlDeclarationBuilder.append(xmlVersion);
          xmlDeclarationBuilder.append('"');
          if (encodingName != null && !"".equals(encodingName))
          {
             xmlDeclarationBuilder.append(" encoding=\"");
             xmlDeclarationBuilder.append(encodingName);
             xmlDeclarationBuilder.append('"');
          }
          if (standalone != null)
          {
             xmlDeclarationBuilder.append(" standalone=\"");
             xmlDeclarationBuilder.append(standalone ? "yes" : "no");
             xmlDeclarationBuilder.append('"');
          }
          xmlDeclarationBuilder.append("?>");
          //Work around to avoid the angle brackets getting escaped.
          outputWriter.writeDTD(xmlDeclarationBuilder.toString());
       }

       /**
        * Special wrapper to wrap write to file in lazy mode. It's means that first try to write
        * will check if file is available.
        */
       private static class FileOutputStreamWrapper
       extends OutputStream
       {
          /** File name.*/
          private final String fileName;

          /** Lazy initialization flag.*/
          private volatile boolean isStarted;

          /** Buffered output Stream.*/
          private Stream stream;

          /**
           * Constructor accepting a file name, which will read after first call.
           *
           * @param    source
           *           A file name.
           */
          private FileOutputStreamWrapper(String source)
          {
             isStarted = false;
             fileName = source;
          }

          /**
           * Write one byte into the stream.
           * @param    b
           *           the data to write.
           * @throws   IOException
           */
          @Override
          public void write(int b)
          throws IOException
          {
             if (!isStarted)
             {
                init(true);
             }
             stream.writeByte((byte) b);
          }

          /**
           * Writes the entire contents of the specified byte array to this output stream.
           *
           * @param    b
           *           The byte array to write.
           *
           * @throws   IOException
           *           if an I/O error occurs. In particular, an IOException may be
           *           thrown if the output stream has been closed.
           * @throws   NullPointerException
           *           if the array is <code>null</code>.
           */
          @Override
          public void write(byte[] b)
          throws IOException,
                 NullPointerException
          {
             write(b, 0, b.length);
          }

          /**
           * Writes <code>len</code> bytes from the specified byte array starting
           * at offset <code>off</code> in this output stream. Element b[off] is
           * the first byte written and b[off+len-1] is the last byte written.
           *
           * @param    b
           *           The array of bytes to write.
           * @param    off
           *           the start offset in the array.
           * @param    len
           *           the number of bytes to write.
           *
           * @throws   IOException
           *           if an I/O error occurs. In particular, an IOException may be
           *           thrown if the output stream has been closed.
           * @throws   NullPointerException
           *           if the array is <code>null</code>.
           * @throws   IndexOutOfBoundsException
           *           if the offset or length are negative, or if offset + length
           *           is larger than the length of the array.
           */
          @Override
          public void write(byte[] b, int off, int len)
          throws IOException,
                 NullPointerException,
                 IndexOutOfBoundsException
          {
             if (!isStarted)
             {
                init(true);
             }
             stream.write(b, off, len);
          }

          /**
           * Close current stream and reset state.
           */
          @Override
          public void close()
          throws IOException
          {
             if (stream != null)
             {
                stream.close();
                isStarted = false;
             }
          }

          /**
           * Initialization method which creates stream wrapper.
           *
           * @param    canWrite
           *           if {@code true} than file will open in read/write mode, otherwise only in
           *           read mode.
           *
           * @throws   IOException
           *           In case of I/O errors.
           */
          private void init(boolean canWrite)
          throws IOException
          {
             try
             {
                stream = StreamFactory.openFileStream(fileName, canWrite, false);
                if (stream == null)
                {
                   throw new IOException("An exception occurred!");
                }
             }
             catch (ErrorConditionException e)
             {
                throw new IOException("An exception occurred!", e);
             }
             isStarted = true;
          }
       }

       /**
        * Special wrapper to wrap write to longchar in lazy mode. It's means that first try to write
        * will check if longchar is available.
        */
       private static class LongcharOutputStream
       extends OutputStream
       {
          /** A valid longchar object to write.*/
          private longchar lchar;

          /** Buffered output Stream.*/
          private StringWriter buffer = new StringWriter();

          /** Lazy initialization flag.*/
          private volatile boolean isStarted;

          /**
           * Constructor accepting a longchar, which will read after first call.
           *
           * @param    source
           *           A valid longchar object.
           */
          private LongcharOutputStream(longchar source)
          {
             lchar = source;
          }

          /**
           * Write one byte into the buffer.
           * @param    b
           *           the data to write.
           */
          @Override
          public void write(int b)
          throws IOException
          {
             if (!isStarted)
             {
                lchar.assign("");
                isStarted = true;
             }
             buffer.write(b);
          }

          /**
           * Flush data from internal buffer to longchar object.
           */
          @Override
          public void flush()
          throws IOException
          {
             String buf = buffer.getBuffer().toString();
             buffer.getBuffer().setLength(0);
             lchar.assign(TextOps.concat(lchar, buf));
          }

          /**
           * Close current stream and reset state.
           */
          @Override
          public void close()
          throws IOException
          {
             flush();
             buffer.close();
             isStarted = false;
          }
       }

       /**
        * Special wrapper to wrap write to memptr in lazy mode. It's means that first try to write
        * will check if memptr is available.
        */
       private static class MemptrOutputStream
       extends OutputStream
       {
          /** A valid memptr */
          private final memptr mptr;

          /** Current read cursor position, started from index 1.*/
          private final AtomicLong position = new AtomicLong();

          /** Lazy initialization flag.*/
          private volatile boolean isStarted = false;

          /** Lazy initialization flag.*/
          private long totalSize = 0;

          /**
           * Constructor accepting a memptr to write.
           *
           * @param    source
           *           A valid memptr object.
           */
          private MemptrOutputStream(memptr source)
          {
             mptr = source;
          }

          /**
           * Write one byte into memptr. If capacity of memptr is not enough then expand capacity.
           * @param    b
           *           the data to write.
           * @throws   IOException
           *           wrap any exception from memptr into IO exception.
           */
          @Override
          public void write(int b)
          throws IOException
          {
             if (!isStarted)
             {
                mptr.setLength(0);  //reset memptr
                position.set(1);
                totalSize = mptr.length().longValue();
                isStarted = true;
             }
             ensureCapacity(1);
             try
             {
                mptr.setByte(b, position.getAndIncrement());
             }
             catch (ErrorConditionException e)
             {
                throw new IOException(e);
             }
          }

          /**
           * Wrap super method to ensure that memptr has enough length and reduce number of calls to
           * expand capacity.
           *
           * @param    b
           *           the data.
           * @param    off
           *           the start offset in the data.
           * @param    len
           *           the number of bytes to write.
           * @throws   IOException
           */
          @Override
          public void write(byte[] b, int off, int len)
          throws IOException
          {
             if (!isStarted)
             {
                mptr.setLength(0);  //reset memptr
                position.set(1);
                totalSize = mptr.length().longValue();
                isStarted = true;
             }
             ensureCapacity(len);
             super.write(b, off, len);
          }

          /**
           * Close current stream and reset state.
           */
          @Override
          public void close()
          throws IOException
          {
             isStarted = false;
          }

          /**
           * Check capacity of memptr, if capacity is less then needed, then increase capacity.
           * @param    len
           *           Count of bytes to ensure capacity.
           */
          private void ensureCapacity(int len)
          {
             long freeSpace = totalSize - position.intValue();
             if (len > freeSpace)
             {
                totalSize = mptr.length().longValue() + len;
                mptr.setLength(totalSize);
             }
          }
       }

       /**
        * Track the namespaces (prefix and uri) for each XML element scope.
        */
       private static class ScopedNamespaceContext
       implements NamespaceContext
       {
          /** Map of prefixes to URIs. */
          private Map<String, String> prefixToUri = null;

          /** The context stack of namespaces for each XML element. */
          private Deque<Map<String, String>> scopes = new ArrayDeque<>();

          /**
           * Notification a new XML element or document starts.
           */
          public void startElement()
          {
             scopes.push(prefixToUri = new HashMap<>());
          }

          /**
           * Notification the XML document or element ends.
           */
          public void endElement()
          {
             prefixToUri = scopes.pop();
          }

          /**
           * Register the given prefix for the given uri.
           *
           * @param    prefix
           *           The namespace prefix to use.
           * @param    uri
           *           The URI to use.
           */
          public void setPrefix(String prefix, String uri)
          {
             prefixToUri.put(prefix, uri);
          }

          /**
           * Get Namespace URI bound to a prefix in the current scope.
           *
           * @param    prefix
           *           The prefix.
           *
           * @return   The namespace URI or <code>null</code> if not found..
           */
          @Override
          public String getNamespaceURI(String prefix)
          {
             String uri = prefixToUri.get(prefix);
             if (uri != null)
             {
                return uri;
             }

             for (Map<String, String> p : scopes)
             {
                uri = p.get(prefix);
                if (uri != null)
                {
                   return uri;
                }
             }

             return null;
          }

          /**
           * Get prefix bound to Namespace URI in the current scope.
           *
           * @param    namespaceURI
           *           The namespace URI.
           *
           * @return   The prefix or <code>null</code> if not found.
           */
          @Override
          public String getPrefix(String namespaceURI)
          {
             BiFunction<Map<String, String>, String, String> findPrefix = (m, uri) ->
             {
                for (Map.Entry<String, String> entry : m.entrySet())
                {
                   if (entry.getValue().equals(uri))
                   {
                      return entry.getKey();
                   }
                }

                return null;
             };

             String prefix = findPrefix.apply(prefixToUri, namespaceURI);
             if (prefix != null)
             {
                return prefix;
             }

             for (Map<String, String> p : scopes)
             {
                prefix = findPrefix.apply(p, namespaceURI);
                if (prefix != null)
                {
                   return prefix;
                }
             }

             return null;
          }

          /**
           * Get all the prefixes associated with the specified URI.
           *
           * @param    namespaceURI
           *           The namespace URI.
           *
           * @return   An iterator for all prefixes for this URI.
           */
          @Override
          public Iterator<String> getPrefixes(String namespaceURI)
          {
             List<String> ret = new ArrayList<>(2);
             BiConsumer<Map<String, String>, String> findPrefix = (m, uri) ->
             {
                for (Map.Entry<String, String> entry : m.entrySet())
                {
                   if (entry.getValue().equals(uri))
                   {
                      ret.add(entry.getKey());
                   }
                }
             };

             findPrefix.accept(prefixToUri, namespaceURI);

             for (Map<String, String> p : scopes)
             {
                findPrefix.accept(p, namespaceURI);
             }

             return ret.iterator();
          }
       }
    }