/*
 * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Blaise Doughan - 2.4 - initial implementation
package org.eclipse.persistence.oxm.record;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.List;

import javax.xml.namespace.QName;

import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.core.helper.CoreConversionManager;
import org.eclipse.persistence.internal.oxm.CharacterEscapeHandler;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.ConversionManager;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.ObjectBuilder;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.XMLBinaryDataHelper;
import org.eclipse.persistence.internal.oxm.XMLMarshaller;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.record.ExtendedContentHandler;
import org.eclipse.persistence.internal.oxm.record.XMLFragmentReader;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

/**
 * <p>Use this type of MarshalRecord when the marshal target is a Writer and the
 * JSON should not be formatted with carriage returns or indenting.</p>
 * <p><code>
 * XMLContext xmlContext = new XMLContext("session-name");<br>
 * XMLMarshaller xmlMarshaller = xmlContext.createMarshaller();<br>
 * JSONRecord jsonWriterRecord = new JSONWriterRecord();<br>
 * jsonWriterRecord.setWriter(myWriter);<br>
 * xmlMarshaller.marshal(myObject, jsonWriterRecord);<br>
 * </code></p>
 * <p>If the marshal(Writer) and setMediaType(MediaType.APPLICATION_JSON) and
 * setFormattedOutput(false) method is called on XMLMarshaller, then the Writer
 * is automatically wrapped in a JSONWriterRecord.</p>
 * <p><code>
 * XMLContext xmlContext = new XMLContext("session-name");<br>
 * XMLMarshaller xmlMarshaller = xmlContext.createMarshaller();<br>
 * xmlMarshaller.setMediaType(MediaType.APPLICATION_JSON);
 * xmlMarshaller xmlMarshaller.setFormattedOutput(false);<br>
 * xmlMarshaller.marshal(myObject, myWriter);<br>
 * </code></p>
 * @see org.eclipse.persistence.oxm.XMLMarshaller
 */
public class JSONWriterRecord extends MarshalRecord<XMLMarshaller> {

    protected boolean isProcessingCData = false;
    protected static final String NULL="null";
    protected String attributePrefix;
    protected boolean charactersAllowed = false;
    protected CharsetEncoder encoder;
    protected CharacterEscapeHandler characterEscapeHandler;
    protected String callbackName;
    protected Output writer;
    protected Level level;

    public JSONWriterRecord(){
        super();
    }

    public JSONWriterRecord(OutputStream outputStream) {
        this();
        writer = new OutputStreamOutput(outputStream);
    }

    public JSONWriterRecord(OutputStream outputStream, String callbackName){
        this(outputStream);
        setCallbackName(callbackName);
    }

    public JSONWriterRecord(Writer writer){
        this();
        setWriter(writer);
    }

    public JSONWriterRecord(Writer writer, String callbackName){
        this(writer);
        setCallbackName(callbackName);
    }

    public void setCallbackName(String callbackName){
        this.callbackName = callbackName;
    }

    /**
     * INTERNAL:
     */
    @Override
    public void setMarshaller(XMLMarshaller marshaller) {
        super.setMarshaller(marshaller);
        attributePrefix = marshaller.getAttributePrefix();
        encoder = Charset.forName(marshaller.getEncoding()).newEncoder();
        if (marshaller.getValueWrapper() != null) {
            textWrapperFragment = new XPathFragment();
            textWrapperFragment.setLocalName(marshaller.getValueWrapper());
        }
        characterEscapeHandler = marshaller.getCharacterEscapeHandler();
        writer.setMarshaller(marshaller);
    }


    /**
     * Handle marshal of an empty collection.
     * @param openGrouping if grouping elements should be marshalled for empty collections
     */
    @Override
    public boolean emptyCollection(XPathFragment xPathFragment, NamespaceResolver namespaceResolver, boolean openGrouping) {
         if(marshaller.isMarshalEmptyCollections()){
             super.emptyCollection(xPathFragment, namespaceResolver, true);
            if (null != xPathFragment) {
                startCollection();
                if (!xPathFragment.isSelfFragment()) {
                    openStartElement(xPathFragment, namespaceResolver);
                    if (null != level) {
                        level.setNeedToCloseComplex(false);
                        level.setNeedToOpenComplex(false);
                    }
                    endElement(xPathFragment, namespaceResolver);
                }
                endEmptyCollection();
            }
             return true;
         }else{
             return super.emptyCollection(xPathFragment, namespaceResolver, openGrouping);
         }
    }

    @Override
    public void forceValueWrapper(){
        charactersAllowed = false;
    }

    /**
     * Return the Writer that the object will be marshalled to.
     * @return The marshal target.
     */
    public Writer getWriter() {
        return writer.getWriter();
    }

    /**
     * Set the Writer that the object will be marshalled to.
     * @param writer The marshal target.
     */
    public void setWriter(Writer writer) {
        this.writer = new WriterOutput(writer);
    }

    @Override
    public void namespaceDeclaration(String prefix, String namespaceURI){
    }

    @Override
    public void defaultNamespaceDeclaration(String defaultNamespace){
    }

    /**
     * INTERNAL:
     */
    @Override
    public void startDocument(String encoding, String version) {
        try {
             if(null != level) {
                 if(level.isFirst()) {
                     level.setFirst(false);
                 } else {
                     writeListSeparator();
                 }
             }else if(callbackName != null){
                 startCallback();
             }
             level = new Level(true, false, false, level);

             writer.write('{');
         } catch (IOException e) {
            throw XMLMarshalException.marshalException(e);
        }
    }

    protected void writeListSeparator() throws IOException{
        writer.write(',');
    }

    protected void writeSeparator() throws IOException{
        writer.write(Constants.COLON);
    }

    /**
     * INTERNAL:
     */
    protected void startCallback() throws IOException{
       if(callbackName != null){
          writer.write(callbackName);
          writer.write('(');
       }
    }

    /**
     * INTERNAL:
     */
    @Override
    public void endDocument() {
        try {
            closeComplex();
            if(null != level && null == level.getPreviousLevel()){
                endCallback();
            }
            level = level.getPreviousLevel();
        } catch (IOException e) {
            throw XMLMarshalException.marshalException(e);
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public void openStartElement(XPathFragment xPathFragment, NamespaceResolver namespaceResolver) {
        try {
             if(level.isFirst()) {
                 level.setFirst(false);
             } else {
                 writer.write(',');
             }
            if(xPathFragment.nameIsText()){
                if(level.isCollection() && level.isEmptyCollection()) {
                    writer.write('[');
                    level.setEmptyCollection(false);
                    level.setNeedToOpenComplex(false);
                    charactersAllowed = true;
                    level = new Level(true, true, false, level);
                    return;
                }
            }

            if(level.needToOpenComplex){
                if (!level.isNestedArray()) {
                    writer.write('{');
                }
                level.needToOpenComplex = false;
                level.needToCloseComplex = true;
           }

           //write the key unless this is a a non-empty collection
           if(!(level.isCollection() && !level.isEmptyCollection())){
               if (!level.isNestedArray()) {
                   writeKey(xPathFragment);
               }
               //if it is the first thing in the collection also add the [
               if(level.isCollection() && level.isEmptyCollection()){
                    writer.write('[');
                       level.setEmptyCollection(false);
               }
           }


            charactersAllowed = true;
            if (xPathFragment.getXMLField() != null && xPathFragment.getXMLField().isNestedArray() && this.marshaller.getJsonTypeConfiguration().isJsonDisableNestedArrayName()) {
                level = new Level(true, true, true, level);
            } else {
                level = new Level(true, true, false, level);
            }
        } catch (IOException e) {
            throw XMLMarshalException.marshalException(e);
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public void element(XPathFragment frag) {
    }

    /**
     * INTERNAL:
     */
    @Override
    public void attribute(String namespaceURI, String localName, String qName, String value) {
        XPathFragment xPathFragment = new XPathFragment();
        xPathFragment.setNamespaceURI(namespaceURI);
        xPathFragment.setAttribute(true);
        xPathFragment.setLocalName(localName);

        openStartElement(xPathFragment, namespaceResolver);
        characters(null, value, null, false, true);
        endElement(xPathFragment, namespaceResolver);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void attribute(XPathFragment xPathFragment, NamespaceResolver namespaceResolver, String value) {
        attribute(xPathFragment, namespaceResolver, value, null);
    }

    /**
     * INTERNAL:
     * override so we don't iterate over namespaces when startPrefixMapping doesn't do anything
     */
    @Override
    public void startPrefixMappings(NamespaceResolver namespaceResolver) {
    }

    /**
     * INTERNAL:
     * override so we don't iterate over namespaces when endPrefixMapping doesn't do anything
     */
    @Override
    public void endPrefixMappings(NamespaceResolver namespaceResolver) {
    }

    /**
     * INTERNAL:
     */
    @Override
    public void closeStartElement() {}

    /**
     * INTERNAL:
     */
    @Override
    public void endElement(XPathFragment xPathFragment, NamespaceResolver namespaceResolver) {
        try{
            if(null != level) {
                if(level.needToOpenComplex){
                    writer.write('{');
                    closeComplex();
                } else if(level.needToCloseComplex && !level.nestedArray){
                    closeComplex();
                }
                charactersAllowed = false;
                level = level.getPreviousLevel();
            }
        } catch (IOException e) {
             throw XMLMarshalException.marshalException(e);
        }
    }

    protected void closeComplex() throws IOException {
        writer.write('}');
    }

    @Override
    public void startCollection() {
        if(null == level) {
            try {
                startCallback();
                writer.write('[');
                level = new Level(true, false, false, level);
            } catch(IOException e) {
                throw XMLMarshalException.marshalException(e);
            }
        } else {
            level.setCollection(true);
            level.setEmptyCollection(true);
            charactersAllowed = false;
        }
    }

    protected void endEmptyCollection(){
        endCollection();
    }

    protected void endCallback() throws IOException{
        if(callbackName != null){
            writer.write(')');
            writer.write(';');
        }
    }

    @Override
    public void endCollection() {
        try {
            if(level != null && null == level.getPreviousLevel()) {
                writer.write(']');
                endCallback();
            } else {
                if(level != null && level.isCollection() && !level.isEmptyCollection()) {
                    writer.write(']');
                }
            }
            level.setCollection(false);
        } catch (IOException e) {
            throw XMLMarshalException.marshalException(e);
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public void characters(String value) {
        characters(value, true, false);
    }
    /**
     * INTERNAL:
     */
     public void characters(String value, boolean isString, boolean isAttribute) {
          boolean textWrapperOpened = false;
          if(!charactersAllowed){
               if(textWrapperFragment != null){
                   openStartElement(textWrapperFragment, namespaceResolver);
                   textWrapperOpened = true;
               }
           }

           level.setNeedToOpenComplex(false);
           try {
               if(isString){
                      writer.write('"');
                      writeValue(value, isAttribute);
                      writer.write('"');
               }else{
                   writer.write(value);
               }

           } catch (IOException e) {
               throw XMLMarshalException.marshalException(e);
           }
           if(textWrapperOpened){
                 if(textWrapperFragment != null){
                      endElement(textWrapperFragment, namespaceResolver);
                 }
             }
     }

     @Override
    public void attribute(XPathFragment xPathFragment, NamespaceResolver namespaceResolver,  Object value, QName schemaType){
         if(xPathFragment.getNamespaceURI() != null && xPathFragment.getNamespaceURI() == javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI){
             return;
         }
         xPathFragment.setAttribute(true);
         openStartElement(xPathFragment, namespaceResolver);
         characters(schemaType, value, null, false, true);
         endElement(xPathFragment, namespaceResolver);
     }

     @Override
    public void characters(QName schemaType, Object value, String mimeType, boolean isCDATA){
        characters(schemaType, value, mimeType, isCDATA, false);
     }

     public void characters(QName schemaType, Object value, String mimeType, boolean isCDATA, boolean isAttribute) {
         if(mimeType != null) {
             if(value instanceof List){
                 value = XMLBinaryDataHelper.getXMLBinaryDataHelper().getBytesListForBinaryValues(//
                         (List)value, marshaller, mimeType);
             }else{

             value = XMLBinaryDataHelper.getXMLBinaryDataHelper().getBytesForBinaryValue(//
                     value, marshaller, mimeType).getData();
             }
         }
         if(schemaType != null && Constants.QNAME_QNAME.equals(schemaType)){
             String convertedValue = getStringForQName((QName)value);
             characters(convertedValue);
         } else if(value.getClass() == String.class){
             //if schemaType is set and it's a numeric or boolean type don't treat as a string
             if(schemaType != null && isNumericOrBooleanType(schemaType)){
                 String convertedValue = ((String) ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).convertObject(value, CoreClassConstants.STRING, schemaType));
                 characters(convertedValue, false, isAttribute);
             }else if(isCDATA){
                 cdata((String)value);
             }else{
                 characters((String)value);
             }
        }else{
            ConversionManager conversionManager = getConversionManager();
            String convertedValue = (String) conversionManager.convertObject(value, CoreClassConstants.STRING, schemaType);
            Class theClass = conversionManager.javaType(schemaType);

            if(schemaType == null || theClass == null){
                if(value.getClass() == CoreClassConstants.BOOLEAN || CoreClassConstants.NUMBER.isAssignableFrom(value.getClass())){
                    characters(convertedValue, false, isAttribute);
                }else{
                    characters(convertedValue);

                }
            }else if(schemaType != null && !isNumericOrBooleanType(schemaType)){
                //if schemaType exists and is not boolean or number do write quotes
                characters(convertedValue);
            } else if(isCDATA){
                cdata(convertedValue);
            }else{
                characters(convertedValue, false, isAttribute);
            }
        }
         charactersAllowed = false;

     }


     private boolean isNumericOrBooleanType(QName schemaType){
         if(schemaType == null){
             return false;
         }else if(schemaType.equals(Constants.BOOLEAN_QNAME)
                 || schemaType.equals(Constants.INTEGER_QNAME)
                 || schemaType.equals(Constants.INT_QNAME)
                 || schemaType.equals(Constants.BYTE_QNAME)
                 || schemaType.equals(Constants.DECIMAL_QNAME)
                 || schemaType.equals(Constants.FLOAT_QNAME)
                 || schemaType.equals(Constants.DOUBLE_QNAME)
                 || schemaType.equals(Constants.SHORT_QNAME)
                 || schemaType.equals(Constants.LONG_QNAME)
                 || schemaType.equals(Constants.NEGATIVE_INTEGER_QNAME)
                 || schemaType.equals(Constants.NON_NEGATIVE_INTEGER_QNAME)
                 || schemaType.equals(Constants.NON_POSITIVE_INTEGER_QNAME)
                 || schemaType.equals(Constants.POSITIVE_INTEGER_QNAME)
                 || schemaType.equals(Constants.UNSIGNED_BYTE_QNAME)
                 || schemaType.equals(Constants.UNSIGNED_INT_QNAME)
                 || schemaType.equals(Constants.UNSIGNED_LONG_QNAME)
                 || schemaType.equals(Constants.UNSIGNED_SHORT_QNAME)
         ){
             return true;
         }
         return false;
     }

    /**
     * INTERNAL:
     */
     @Override
    public void namespaceDeclarations(NamespaceResolver namespaceResolver) {
     }

    /**
     * INTERNAL:
     */
     @Override
    public void nilComplex(XPathFragment xPathFragment, NamespaceResolver namespaceResolver){
         XPathFragment groupingFragment = openStartGroupingElements(namespaceResolver);
         closeStartGroupingElements(groupingFragment);
         openStartElement(xPathFragment, namespaceResolver);
         characters(NULL, false, false);
         endElement(xPathFragment, namespaceResolver);
     }

    /**
     * INTERNAL:
     */
     @Override
    public void nilSimple(NamespaceResolver namespaceResolver){
         XPathFragment groupingFragment = openStartGroupingElements(namespaceResolver);
         characters(NULL, false, false);
         closeStartGroupingElements(groupingFragment);
     }

     /**
      * Used when an empty simple value should be written
      * @since EclipseLink 2.4
      */
     @Override
    public void emptySimple(NamespaceResolver namespaceResolver){
         nilSimple(namespaceResolver);
     }

     @Override
    public void emptyAttribute(XPathFragment xPathFragment,NamespaceResolver namespaceResolver){
         XPathFragment groupingFragment = openStartGroupingElements(namespaceResolver);
         openStartElement(xPathFragment, namespaceResolver);
         characters(NULL, false, false);
         endElement(xPathFragment, namespaceResolver);
         closeStartGroupingElements(groupingFragment);
     }

     /**
      * Used when an empty complex item should be written
      * @since EclipseLink 2.4
      */
     @Override
    public void emptyComplex(XPathFragment xPathFragment, NamespaceResolver namespaceResolver){
         XPathFragment groupingFragment = openStartGroupingElements(namespaceResolver);
         closeStartGroupingElements(groupingFragment);
         openStartElement(xPathFragment, namespaceResolver);
         endElement(xPathFragment, namespaceResolver);
     }

     /**
      * INTERNAL:
      */
     @Override
     public void marshalWithoutRootElement(ObjectBuilder treeObjectBuilder, Object object, Descriptor descriptor, Root root, boolean isXMLRoot){
         if(treeObjectBuilder != null){
             addXsiTypeAndClassIndicatorIfRequired(descriptor, null, descriptor.getDefaultRootElementField(), root, object, isXMLRoot, true);
             treeObjectBuilder.marshalAttributes(this, object, session);
         }
      }

    /**
     * INTERNAL:
     */
    @Override
    public void cdata(String value) {
        characters(value);
    }

    /**
     * INTERNAL:
     * The character used to separate the prefix and uri portions when namespaces are present
     * @since 2.4
     */
    @Override
    public char getNamespaceSeparator(){
        return marshaller.getNamespaceSeparator();
    }

    /**
     * INTERNAL:
     * The optional fragment used to wrap the text() mappings
     * @since 2.4
     */
    @Override
    public XPathFragment getTextWrapperFragment() {
        return textWrapperFragment;
    }

    protected void writeKey(XPathFragment xPathFragment) throws IOException {
        if (xPathFragment.getLocalName() != null && !xPathFragment.getLocalName().equals(Constants.EMPTY_STRING)) {
            super.openStartElement(xPathFragment, namespaceResolver);
            writer.write('"');
            if (xPathFragment.isAttribute() && attributePrefix != null) {
                writer.writeAttributePrefix();
            }

            if (isNamespaceAware()) {
                if (xPathFragment.getNamespaceURI() != null) {
                    String prefix = null;
                    if (getNamespaceResolver() != null) {
                        prefix = getNamespaceResolver().resolveNamespaceURI(xPathFragment.getNamespaceURI());
                    } else if (namespaceResolver != null) {
                        prefix = namespaceResolver.resolveNamespaceURI(xPathFragment.getNamespaceURI());
                    }
                    if (prefix != null && !prefix.equals(Constants.EMPTY_STRING)) {
                        writer.write(prefix);
                        writer.writeNamespaceSeparator();
                    }
                }
            }

            writer.writeLocalName(xPathFragment);
            writer.write('"');

            writeSeparator();
        }
    }

    /**
     * INTERNAL:
     */
    protected void writeValue(String value, boolean isAttribute) {
        try {
               if (characterEscapeHandler != null) {
                   writer.writeResultFromCharEscapeHandler(value, isAttribute);
                   return;
               }

              char[] chars = value.toCharArray();
              for (int x = 0, charsSize = chars.length; x < charsSize; x++) {
                  char character = chars[x];
                  switch (character){
                      case '"' : {
                          writer.write("\\\"");
                          break;
                      }
                      case '\b': {
                          writer.write("\\b");
                          break;
                      }
                      case '\f': {
                          writer.write("\\f");
                          break;
                      }
                      case '\n': {
                          writer.write("\\n");
                          break;
                      }
                      case '\r': {
                          writer.write("\\r");
                          break;
                      }
                      case '\t': {
                          writer.write("\\t");
                          break;
                      }
                      case '\\': {
                          writer.write("\\\\");
                          break;
                      }
                      default: {
                          if(Character.isISOControl(character) || !encoder.canEncode(character)){
                              writer.write("\\u");
                              String hex = Integer.toHexString(character).toUpperCase();
                              for(int i=hex.length(); i<4; i++){
                                  writer.write("0");
                              }
                              writer.write(hex);
                          }else{
                              writer.write(character);
                          }
                      }
                  }
              }
        } catch (IOException e) {
            throw XMLMarshalException.marshalException(e);
        }
    }

    @Override
    protected String getStringForQName(QName qName){
        if(null == qName) {
            return null;
        }
        CoreConversionManager xmlConversionManager = getSession().getDatasourcePlatform().getConversionManager();

        return (String) xmlConversionManager.convertObject(qName, String.class);
    }

    /**
     * Receive notification of a node.
     * @param node The Node to be added to the document
     * @param namespaceResolver The NamespaceResolver can be used to resolve the
     * namespace URI/prefix of the node
     */
    @Override
    public void node(Node node, NamespaceResolver namespaceResolver, String uri, String name) {
        if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
            Attr attr = (Attr) node;
            String resolverPfx = null;
            if (getNamespaceResolver() != null) {
                resolverPfx = this.getNamespaceResolver().resolveNamespaceURI(attr.getNamespaceURI());
            }
            String namespaceURI = attr.getNamespaceURI();
            // If the namespace resolver contains a prefix for the attribute's URI,
            // use it instead of what is set on the attribute
            if (resolverPfx != null) {
                attribute(attr.getNamespaceURI(), Constants.EMPTY_STRING, resolverPfx+Constants.COLON+attr.getLocalName(), attr.getNodeValue());
            } else {
                attribute(attr.getNamespaceURI(), Constants.EMPTY_STRING, attr.getName(), attr.getNodeValue());
                // May need to declare the URI locally
                if (attr.getNamespaceURI() != null) {
                    attribute(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, Constants.EMPTY_STRING, javax.xml.XMLConstants.XMLNS_ATTRIBUTE + Constants.COLON + attr.getPrefix(), attr.getNamespaceURI());
                    this.getNamespaceResolver().put(attr.getPrefix(), attr.getNamespaceURI());
                }
            }
        } else if (node.getNodeType() == Node.TEXT_NODE) {
            characters(node.getNodeValue(), false, false);
        } else {
            try {
                JSONWriterRecordContentHandler wrcHandler = new JSONWriterRecordContentHandler();

                XMLFragmentReader xfragReader = new XMLFragmentReader(namespaceResolver);
                xfragReader.setContentHandler(wrcHandler);
                xfragReader.setProperty("http://xml.org/sax/properties/lexical-handler", wrcHandler);
                xfragReader.parse(node, uri, name);
            } catch (SAXException sex) {
                throw XMLMarshalException.marshalException(sex);
            }
        }
    }

    @Override
    public boolean isWrapperAsCollectionName() {
        return marshaller.isWrapperAsCollectionName();
    }

    @Override
    public void flush() {
        try {
            writer.flush();
        } catch(IOException e) {
            throw XMLMarshalException.marshalException(e);
        }
    }

    /**
     * This class will typically be used in conjunction with an XMLFragmentReader.
     * The XMLFragmentReader will walk a given XMLFragment node and report events
     * to this class - the event's data is then written to the enclosing class'
     * writer.
     *
     * @see org.eclipse.persistence.internal.oxm.record.XMLFragmentReader
     */
    protected class JSONWriterRecordContentHandler implements ExtendedContentHandler, LexicalHandler {

        JSONWriterRecordContentHandler() {
        }

        // --------------------- CONTENTHANDLER METHODS --------------------- //
        @Override
        public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
                XPathFragment xPathFragment = new XPathFragment(localName);
                xPathFragment.setNamespaceURI(namespaceURI);
                openStartElement(xPathFragment, namespaceResolver);
                handleAttributes(atts);
        }

        @Override
        public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
            XPathFragment xPathFragment = new XPathFragment(localName);
            xPathFragment.setNamespaceURI(namespaceURI);

            JSONWriterRecord.this.endElement(xPathFragment, namespaceResolver);
        }

        @Override
        public void startPrefixMapping(String prefix, String uri) throws SAXException {
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            String characters = new String (ch, start, length);
            characters(characters);
        }

        @Override
        public void characters(CharSequence characters) throws SAXException {
            JSONWriterRecord.this.characters(characters.toString());
        }

        // --------------------- LEXICALHANDLER METHODS --------------------- //
        @Override
        public void comment(char[] ch, int start, int length) throws SAXException {
        }

        @Override
        public void startCDATA() throws SAXException {
            isProcessingCData = true;
        }

        @Override
        public void endCDATA() throws SAXException {
            isProcessingCData = false;
        }

        // --------------------- CONVENIENCE METHODS --------------------- //
           protected void handleAttributes(Attributes atts) {
            for (int i=0, attsLength = atts.getLength(); i<attsLength; i++) {
                String qName = atts.getQName(i);
                if((qName != null && (qName.startsWith(javax.xml.XMLConstants.XMLNS_ATTRIBUTE + Constants.COLON) || qName.equals(javax.xml.XMLConstants.XMLNS_ATTRIBUTE)))) {
                    continue;
                }
                attribute(atts.getURI(i), atts.getLocalName(i), qName, atts.getValue(i));
            }
        }

        protected void writeComment(char[] chars, int start, int length) {
        }

        protected void writeCharacters(char[] chars, int start, int length) {
            try {
                characters(chars, start, length);
            } catch (SAXException e) {
                throw XMLMarshalException.marshalException(e);
            }
        }
        // --------------- SATISFY CONTENTHANDLER INTERFACE --------------- //
        @Override
        public void endPrefixMapping(String prefix) throws SAXException {}
        @Override
        public void processingInstruction(String target, String data) throws SAXException {}
        @Override
        public void setDocumentLocator(Locator locator) {}
        @Override
        public void startDocument() throws SAXException {}
        @Override
        public void endDocument() throws SAXException {}
        @Override
        public void skippedEntity(String name) throws SAXException {}
        @Override
        public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {}

        // --------------- SATISFY LEXICALHANDLER INTERFACE --------------- //
        @Override
        public void startEntity(String name) throws SAXException {}
        @Override
        public void endEntity(String name) throws SAXException {}
        @Override
        public void startDTD(String name, String publicId, String systemId) throws SAXException {}
        @Override
        public void endDTD() throws SAXException {}
        @Override
        public void setNil(boolean isNil) {}

    }

    /**
     * Instances of this class are used to maintain state about the current
     * level of the JSON message being marshalled.
     */
    protected static class Level {

        private boolean first;
        private boolean collection;
        private boolean emptyCollection;
        private boolean needToOpenComplex;
        private boolean needToCloseComplex;
        private boolean nestedArray;
        private Level previousLevel;

        public Level(boolean value, boolean needToOpen, boolean nestedArray) {
            this.first = value;
            needToOpenComplex = needToOpen;
            this.nestedArray = nestedArray;
        }

        public Level(boolean value, boolean needToOpen, boolean nestedArray, Level previousLevel) {
            this(value, needToOpen, nestedArray);
            this.previousLevel = previousLevel;
        }

        public boolean isNeedToOpenComplex() {
            return needToOpenComplex;
        }

        public void setNeedToOpenComplex(boolean needToOpenComplex) {
            this.needToOpenComplex = needToOpenComplex;
        }

        public boolean isNeedToCloseComplex() {
            return needToCloseComplex;
        }

        public void setNeedToCloseComplex(boolean needToCloseComplex) {
            this.needToCloseComplex = needToCloseComplex;
        }

        public boolean isEmptyCollection() {
            return emptyCollection;
        }

        public void setEmptyCollection(boolean emptyCollection) {
            this.emptyCollection = emptyCollection;
        }

        public boolean isFirst() {
            return first;
        }

        public void setFirst(boolean value) {
            this.first = value;
        }

        public boolean isCollection() {
            return collection;
        }

        public void setCollection(boolean collection) {
            this.collection = collection;
        }

        public Level getPreviousLevel() {
            return previousLevel;
        }

        public boolean isNestedArray() {
            return nestedArray;
        }

        public void setNestedArray(boolean nestedArray) {
            this.nestedArray = nestedArray;
        }
    }

    protected static interface Output {

        void flush() throws IOException;

        XMLMarshaller getMarshaller();

        OutputStream getOutputStream();

        Writer getWriter();

        void setMarshaller(XMLMarshaller marshaller);

        void write(char character) throws IOException;

        void write(String text) throws IOException;

        void writeAttributePrefix() throws IOException;

        void writeCR() throws IOException;

        void writeLocalName(XPathFragment xPathFragment) throws IOException;

        void writeNamespaceSeparator() throws IOException;

        void writeResultFromCharEscapeHandler(String value, boolean isAttribute);

    }

    protected static class OutputStreamOutput implements Output {

        private static final int BUFFER_SIZE = 512;

        private byte[] attributePrefix;
        private byte[] buffer = new byte[BUFFER_SIZE];
        private int bufferIndex = 0;
        private CharacterEscapeHandler characterEscapeHandler;
        private byte[] cr = Constants.cr().getBytes(Constants.DEFAULT_CHARSET);
        private XMLMarshaller marshaller;
        private char namespaceSeparator;
        private OutputStream outputStream;

        protected OutputStreamOutput(OutputStream writer) {
            this.outputStream = writer;
        }

        @Override
        public void flush() throws IOException {
            outputStream.write(buffer, 0, bufferIndex);
            bufferIndex = 0;
            outputStream.flush();
        }

        @Override
        public XMLMarshaller getMarshaller() {
            return marshaller;
        }

        @Override
        public OutputStream getOutputStream() {
            return outputStream;
        }

        @Override
        public Writer getWriter() {
             return null;
        }

        @Override
        public void setMarshaller(XMLMarshaller marshaller) {
            this.marshaller = marshaller;
            String attributePrefix = marshaller.getAttributePrefix();
            if(null != attributePrefix) {
                this.attributePrefix = attributePrefix.getBytes(Constants.DEFAULT_CHARSET);
            }
            this.characterEscapeHandler = marshaller.getCharacterEscapeHandler();
            this.namespaceSeparator = marshaller.getNamespaceSeparator();
        }

        private void write(byte[] bytes) {
            int bytesLength = bytes.length;
            if(bufferIndex + bytesLength >= BUFFER_SIZE) {
                try {
                    outputStream.write(buffer, 0, bufferIndex);
                    bufferIndex = 0;
                    if(bytesLength > BUFFER_SIZE) {
                        outputStream.write(bytes);
                        return;
                    }
                } catch(IOException e) {
                    throw XMLMarshalException.marshalException(e);
                }
            }
            System.arraycopy(bytes, 0, buffer, bufferIndex, bytes.length);
            bufferIndex += bytesLength;
        }

        @Override
        public void write(char character) throws IOException {
            if (character > 0x7F) {
                if(character > 0x7FF) {
                    if((character >= Character.MIN_HIGH_SURROGATE) && (character <= Character.MAX_LOW_SURROGATE)) {
                        int uc = ((character & 0x3ff) << 10);
                        // 11110zzz
                        write((byte)(0xF0 | ((uc >> 18))));
                        // 10zzyyyy
                        write((byte)(0x80 | ((uc >> 12) & 0x3F)));
                        // 10yyyyxx
                        write((byte)(0x80 | ((uc >> 6) & 0x3F)));
                        // 10xxxxxx
                        write((byte)(0x80 + (uc & 0x3F)));
                        return;
                    } else {
                        // 1110yyyy
                        write((byte)(0xE0 + (character >> 12)));
                    }
                    // 10yyyyxx
                    write((byte)(0x80 + ((character >> 6) & 0x3F)));
                } else {
                    // 110yyyxx
                    write((byte)(0xC0 + (character >> 6)));
                }
                write((byte)(0x80 + (character & 0x3F)));
            } else {
                write((byte) character);
            }
        }

        private void write(byte b) {
            if(bufferIndex == BUFFER_SIZE) {
                try {
                    outputStream.write(buffer, 0, BUFFER_SIZE);
                    bufferIndex = 0;
                } catch(IOException e) {
                    throw XMLMarshalException.marshalException(e);
                }
            }
            buffer[bufferIndex++] = b;
        }

        @Override
        public void write(String text) throws IOException {
            write(text.getBytes(Constants.DEFAULT_CHARSET));
        }

        @Override
        public void writeAttributePrefix() throws IOException {
            write(attributePrefix);
        }

        @Override
        public void writeCR() throws IOException {
            write(cr);
        }

        @Override
        public void writeLocalName(XPathFragment xPathFragment) throws IOException {
            write(xPathFragment.getLocalNameBytes());
        }

        @Override
        public void writeNamespaceSeparator() throws IOException {
            write(namespaceSeparator);
        }

        @Override
        public void writeResultFromCharEscapeHandler(String value, boolean isAttribute) {
            try {
                CharArrayWriter out = new CharArrayWriter();
                characterEscapeHandler.escape(value.toCharArray(), 0, value.length(), isAttribute, out);
                byte[] bytes = out.toString().getBytes();
                write(bytes);
                out.close();
            } catch (IOException e) {
                throw XMLMarshalException.marshalException(e);
            }
        }

    }

    private static class WriterOutput implements Output {

        private String attributePrefix;
        private CharacterEscapeHandler characterEscapeHandler;
        private String cr = Constants.cr();
        private XMLMarshaller marshaller;
        private char namespaceSeparator;
        private Writer writer;

        @Override
        public void flush() throws IOException {
            writer.flush();
        }

        protected WriterOutput(Writer writer) {
            this.writer = writer;
        }

        @Override
        public XMLMarshaller getMarshaller() {
            return marshaller;
        }

        @Override
        public OutputStream getOutputStream() {
            return null;
        }

        @Override
        public Writer getWriter() {
            return writer;
        }

        @Override
        public void setMarshaller(XMLMarshaller marshaller) {
            this.marshaller = marshaller;
            this.attributePrefix = marshaller.getAttributePrefix();
            this.characterEscapeHandler = marshaller.getCharacterEscapeHandler();
            this.namespaceSeparator = marshaller.getNamespaceSeparator();
        }

        @Override
        public void writeAttributePrefix() throws IOException {
            writer.write(attributePrefix);
        }

        @Override
        public void write(char character) throws IOException {
            writer.write(character);
        }

        @Override
        public void write(String text) throws IOException {
            writer.write(text);
        }

        @Override
        public void writeCR() throws IOException {
            writer.write(cr);
        }

        @Override
        public void writeLocalName(XPathFragment xPathFragment) throws IOException {
            writer.write(xPathFragment.getLocalName());
        }

        @Override
        public void writeNamespaceSeparator() throws IOException {
            writer.write(namespaceSeparator);
        }

        @Override
        public void writeResultFromCharEscapeHandler(String value, boolean isAttribute) {
            try {
                characterEscapeHandler.escape(value.toCharArray(), 0, value.length(), isAttribute, writer);
            } catch (IOException e) {
                throw XMLMarshalException.marshalException(e);
            }
        }

    }

}
