/*
 * Copyright (c) 2013, 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:
//     Denise Smith - 2.6 - initial implementation
//     Radek Felman - 2.7.5 - Bug 389815 - Enhancement Request - JSON specific multidimensional array support
package org.eclipse.persistence.oxm.record;

import java.io.IOException;
import java.io.StringWriter;
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;

public abstract class JsonRecord<T extends JsonRecord.Level> extends MarshalRecord<XMLMarshaller> {

    protected T position;
    protected CharacterEscapeHandler characterEscapeHandler;
    protected String attributePrefix;
    protected boolean isRootArray;
    protected static final String NULL = "null";
    protected boolean isLastEventStart;

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

    @Override
    public void forceValueWrapper() {
        setComplex(position, true);
        isLastEventStart = false;
    }

    @Override
    public void startDocument(String encoding, String version) {
        if (isRootArray) {
            if (position == null) {
                startCollection();
            }
            position.setEmptyCollection(false);

            position = createNewLevel(false, position, false);

            isLastEventStart = true;
        } else {
            startRootObject();
        }
    }

    protected T createNewLevel(boolean collection, T parentLevel, boolean nestedArray) {
        return (T) new Level(collection, position, nestedArray);
    }

    protected void startRootObject() {
        position = createNewLevel(false, null, false);
    }


    @Override
    public void openStartElement(XPathFragment xPathFragment, NamespaceResolver namespaceResolver) {
        super.openStartElement(xPathFragment, namespaceResolver);
        String keyName1 = getKeyName(xPathFragment);
        if (position != null && position.isCollection && xPathFragment.getXMLField() != null && xPathFragment.getXMLField().isNestedArray()
                && this.marshaller.getJsonTypeConfiguration().isJsonDisableNestedArrayName()) {
            position.addSkip();
            position.setKeyName(keyName1);
            if (!position.isEmptyCollectionGenerated()) {
                startEmptyCollection();
                position.setEmptyCollectionGenerated(true);
            }
            return;
        }
        if (position != null) {
            T newLevel;
            if (xPathFragment.getXMLField() != null && xPathFragment.getXMLField().isNestedArray() && this.marshaller.getJsonTypeConfiguration().isJsonDisableNestedArrayName()) {
                newLevel = createNewLevel(false, position, true);
            } else {
                newLevel = createNewLevel(false, position, false);
            }

            if (isLastEventStart) {
                //this means 2 startevents in a row so the last this is a complex object
                setComplex(position, true);
            }

            String keyName = getKeyName(xPathFragment);
            if (keyName != null && !keyName.equals(Constants.EMPTY_STRING)) {
                if (position.isCollection && position.isEmptyCollection()) {
                    position.setKeyName(keyName);
                    startEmptyCollection();
                } else {
                    newLevel.setKeyName(keyName);
                }
            }
            if (!(newLevel.isNestedArray() && newLevel.isComplex())) {
                position = newLevel;
            }
            isLastEventStart = true;
        }
    }

    protected void startEmptyCollection() {
    }

    /**
     * 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) {

                if (xPathFragment.isSelfFragment() || xPathFragment.nameIsText()) {
                    String keyName = position.getKeyName();
                    setComplex(position, false);
                    writeEmptyCollection((T) position.parentLevel, keyName);
                } else {
                    if (isLastEventStart) {
                        setComplex(position, true);
                    }
                    String keyName = getKeyName(xPathFragment);
                    if (keyName != null) {
                        writeEmptyCollection(position, keyName);
                    }
                }
                isLastEventStart = false;
            }

            return true;
        } else {
            return super.emptyCollection(xPathFragment, namespaceResolver, openGrouping);
        }
    }

    protected abstract void writeEmptyCollection(T level, String keyName);

    @Override
    public void endDocument() {
        if (position != null) {
            finishLevel();
        }
    }

    protected void finishLevel() {
        boolean notSkip = position.parentLevel == null || position.parentLevel.notSkip();
        if (notSkip) {
            position = (T) position.parentLevel;
        }
    }

    @Override
    public void startCollection() {
        if (position == null) {
            isRootArray = true;
            position = createNewLevel(true, null, false);
            startRootLevelCollection();
        } else {
            if (isLastEventStart) {
                setComplex(position, true);
            }
            position = createNewLevel(true, position, position.isNestedArray());
        }
        isLastEventStart = false;
    }

    protected void setComplex(T level, boolean complex) {
        level.setComplex(complex);
    }

    protected abstract void startRootLevelCollection();

    protected String getKeyName(XPathFragment xPathFragment) {
        String keyName = xPathFragment.getLocalName();

        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)) {
                    keyName = prefix + getNamespaceSeparator() + keyName;
                }
            }
        }
        if (xPathFragment.isAttribute() && attributePrefix != null) {
            keyName = attributePrefix + keyName;
        }

        return keyName;
    }

    @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);
    }

    /**
     * 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:
     * 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;
    }

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

    @Override
    public void element(XPathFragment frag) {
        isLastEventStart = false;
    }


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

    @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);

    }

    @Override
    public void closeStartElement() {
    }

    @Override
    public void characters(String value) {
        writeValue(value, null, false);
    }

    @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);
            writeValue(convertedValue, null, isAttribute);
        } 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)) {
                ConversionManager conversionManager = getConversionManager();
                Class<?> theClass = conversionManager.javaType(schemaType);
                Object convertedValue = conversionManager.convertObject(value, theClass, schemaType);
                writeValue(convertedValue, schemaType, isAttribute);
            } else if (isCDATA) {
                cdata((String) value);
            } else {
                writeValue(value, null, isAttribute);
            }
        } else {
            Class<?> theClass = ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).javaType(schemaType);

            if (schemaType == null || theClass == null) {
                if (value.getClass() == CoreClassConstants.BOOLEAN || CoreClassConstants.NUMBER.isAssignableFrom(value.getClass())) {
                    writeValue(value, schemaType, isAttribute);
                } else {
                    String convertedValue = ((String) ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).convertObject(value, CoreClassConstants.STRING, schemaType));
                    writeValue(convertedValue, schemaType, isAttribute);
                }
            } else if (schemaType != null && !isNumericOrBooleanType(schemaType)) {
                //if schemaType exists and is not boolean or number do write quotes (convert to string)
                String convertedValue = ((String) ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).convertObject(value, CoreClassConstants.STRING, schemaType));
                writeValue(convertedValue, schemaType, isAttribute);
            } else if (isCDATA) {
                String convertedValue = ((String) ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).convertObject(value, CoreClassConstants.STRING, schemaType));
                cdata(convertedValue);
            } else {
                writeValue(value, schemaType, isAttribute);
            }
        }
    }


    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;
    }

    public void writeValue(Object value, QName schemaType, boolean isAttribute) {

        if (characterEscapeHandler != null && value instanceof String) {
            try {
                StringWriter stringWriter = new StringWriter();
                characterEscapeHandler.escape(((String) value).toCharArray(), 0, ((String) value).length(), isAttribute, stringWriter);
                value = stringWriter.toString();
            } catch (IOException e) {
                throw XMLMarshalException.marshalException(e);
            }
        }

        boolean textWrapperOpened = false;
        if (!isLastEventStart) {
            openStartElement(textWrapperFragment, namespaceResolver);
            textWrapperOpened = true;
        }

        T currentLevel = position;
        String keyName = position.getKeyName();
        if (!position.isComplex) {
            currentLevel = (T) position.parentLevel;
        }
        addValue(currentLevel, keyName, value, schemaType);
        isLastEventStart = false;
        if (textWrapperOpened) {
            endElement(textWrapperFragment, namespaceResolver);
        }
    }

    @Override
    public void endElement(XPathFragment xPathFragment, NamespaceResolver namespaceResolver) {
        if (position != null) {
            if (isLastEventStart) {
                setComplex(position, true);
            }
            if (position.isComplex) {
                finishLevel();
            } else {
                position = (T) position.parentLevel;
            }
            isLastEventStart = false;
        }
    }

    private void addValue(T currentLevel, String keyName, Object value, QName schemaType) {
        if (currentLevel.isCollection()) {
            addValueToArray(currentLevel, value, schemaType);
            currentLevel.setEmptyCollection(false);
        } else {
            addValueToObject(currentLevel, keyName, value, schemaType);
        }
    }

    protected abstract void addValueToObject(T currentLevel, String keyName, Object value, QName schemaType);

    protected abstract void addValueToArray(T currentLevel, Object value, QName schemaType);

    @Override
    public void cdata(String value) {
        characters(value);
    }

    @Override
    public void node(Node node, NamespaceResolver resolver, 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());
            }
            // 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) {
            writeValue(node.getNodeValue(), null, false);
        } else {
            try {
                JsonRecordContentHandler wrcHandler = new JsonRecordContentHandler();

                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
    protected String getStringForQName(QName qName) {
        if (null == qName) {
            return null;
        }
        CoreConversionManager xmlConversionManager = getSession().getDatasourcePlatform().getConversionManager();

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

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

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

    @Override
    public void defaultNamespaceDeclaration(String defaultNamespace) {
    }

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

    /**
     * INTERNAL:
     */
    @Override
    public void nilSimple(NamespaceResolver namespaceResolver) {
        XPathFragment groupingFragment = openStartGroupingElements(namespaceResolver);
        characters(NULL);
        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);
        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);
    }


    /**
     * 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 JsonRecordContentHandler implements ExtendedContentHandler, LexicalHandler {

        JsonRecordContentHandler() {
        }

        // --------------------- 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);

            JsonRecord.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 {
            JsonRecord.this.characters(characters.toString());
        }

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

        @Override
        public void startCDATA() throws SAXException {
        }

        @Override
        public void endCDATA() throws SAXException {
        }

        // --------------------- 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 {

        protected boolean isCollection;
        protected boolean emptyCollection;
        protected boolean emptyCollectionGenerated;
        protected String keyName;
        protected boolean isComplex;
        protected boolean nestedArray;
        protected Level parentLevel;
        private int skipCount;

        public Level(boolean isCollection, Level parentLevel, boolean nestedArray) {
            setCollection(isCollection);
            emptyCollection = true;
            this.parentLevel = parentLevel;
            this.nestedArray = nestedArray;
            this.skipCount = 0;
        }

        protected void addSkip() {
            skipCount++;
        }

        protected boolean notSkip() {
            if (skipCount > 0) {
                skipCount--;
                return false;
            } else {
                return true;
            }
        }

        protected int getSkipCount() {
            return skipCount;
        }

        public boolean isCollection() {
            return isCollection;
        }

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

        public String getKeyName() {
            return keyName;
        }

        public void setKeyName(String keyName) {
            this.keyName = keyName;
        }

        public boolean isEmptyCollection() {
            return emptyCollection;
        }

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

        public boolean isEmptyCollectionGenerated() {
            return emptyCollectionGenerated;
        }

        public void setEmptyCollectionGenerated(boolean emptyCollectionGenerated) {
            this.emptyCollectionGenerated = emptyCollectionGenerated;
        }

        public boolean isComplex() {
            return isComplex;
        }

        public void setComplex(boolean isComplex) {
            this.isComplex = isComplex;
        }

        public boolean isNestedArray() {
            return nestedArray;
        }

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

    }

}
