/*
 * 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
//     Juan Pablo Gardella = 2.7.4 - Fix for the bug #543063
package org.eclipse.persistence.internal.oxm.record.json;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
import jakarta.json.JsonException;
import jakarta.json.JsonReader;
import jakarta.json.JsonStructure;
import jakarta.json.JsonArray;
import jakarta.json.JsonNumber;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import jakarta.json.JsonValue.ValueType;
import javax.xml.namespace.QName;

import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.oxm.CollectionGroupingElementNodeValue;
import org.eclipse.persistence.internal.oxm.ConversionManager;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.ContainerValue;
import org.eclipse.persistence.internal.oxm.MediaType;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.NodeValue;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.Unmarshaller;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.record.AbstractUnmarshalRecord;
import org.eclipse.persistence.internal.oxm.record.SAXUnmarshallerHandler;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;
import org.eclipse.persistence.internal.oxm.XPathNode;
import org.eclipse.persistence.internal.oxm.record.XMLReaderAdapter;
import org.eclipse.persistence.internal.oxm.record.deferred.DeferredContentHandler;
import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy;
import org.eclipse.persistence.oxm.record.XMLRootRecord;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

public class JsonStructureReader extends XMLReaderAdapter {

    private static final String TRUE = "true";
    private static final String FALSE = "false";
    private String attributePrefix = null;
    private NamespaceResolver namespaces = null;
    private boolean includeRoot;
    private String textWrapper;
    private Class unmarshalClass;
    private boolean isInCollection;
    private JsonStructure jsonStructure;
    private JsonAttributes attributes = new JsonAttributes();

    /**
     * If we should treat unqualified type property in JSON as MOXy type discriminator.
     */
    private boolean jsonTypeCompatibility;

    public JsonStructureReader(Unmarshaller u) {
        this(u, null);
    }

    public JsonStructureReader(Unmarshaller u, Class clazz) {
        this.attributePrefix = u.getAttributePrefix();
        if (Constants.EMPTY_STRING.equals(attributePrefix)) {
            attributePrefix = null;
        }
        namespaces = u.getNamespaceResolver();

        setNamespaceAware(u.getNamespaceResolver() != null);
        setNamespaceSeparator(u.getNamespaceSeparator());
        this.includeRoot = u.isIncludeRoot();
        this.setErrorHandler(u.getErrorHandler());
        this.textWrapper = u.getValueWrapper();
        this.unmarshalClass = clazz;
        this.jsonTypeCompatibility = u.getJsonTypeConfiguration().useJsonTypeCompatibility();
    }

    public void setJsonStructure(JsonStructure jsonStructure) {
        this.jsonStructure = jsonStructure;
    }

    @Override
    public void parse(InputSource input) throws IOException, SAXException, JsonException {
        if (input == null) {
            if (jsonStructure != null) {
                parseRoot(jsonStructure);
            }
            return;
        }

        try {
            InputStream inputStream = null;
            JsonReader jsonReader;
            if (null != input.getByteStream()) {
                inputStream = input.getByteStream();
                jsonReader = Json.createReader(inputStream);
            } else if (null != input.getCharacterStream()) {
                jsonReader = Json.createReader(input.getCharacterStream());
            } else {
                try {
                    URL url = new URL(input.getSystemId());
                    inputStream = url.openStream();
                } catch (MalformedURLException malformedURLException) {
                    try {
                        inputStream = new FileInputStream(input.getSystemId());
                    } catch (FileNotFoundException fileNotFoundException) {
                        throw malformedURLException;
                    }
                }
                jsonReader = Json.createReader(inputStream);
            }
            if (jsonReader != null) {
                JsonStructure structure = jsonReader.read();
                parseRoot(structure);
            }

            if (null != inputStream) {
                inputStream.close();
            }
        } catch (JsonException je) {
            throw XMLMarshalException.unmarshalException(je);
        }
    }

    @Override
    public void parse(String systemId) {
        try {
            parse(new InputSource(systemId));
        } catch (IOException | SAXException e) {
            throw XMLMarshalException.unmarshalException(e);
        }
    }

    public void parseRoot(JsonValue jsonValue) throws SAXException {
        if (namespaces != null) {
            Map<String, String> namespacePairs = namespaces.getPrefixesToNamespaces();
            for (Entry<String, String> namespacePair : namespacePairs.entrySet()) {
                contentHandler.startPrefixMapping(namespacePair.getKey(), namespacePair.getValue());
            }
        }

        if (jsonValue.getValueType() == ValueType.OBJECT) {
            contentHandler.startDocument();
            JsonObject jsonObject = (JsonObject) jsonValue;

            Set<Entry<String, JsonValue>> children = jsonObject.entrySet();
            if (children.size() == 0 && unmarshalClass == null) {
                return;
            }

            Iterator<Entry<String, JsonValue>> iter = children.iterator();

            if (includeRoot) {
                if (children.size() > 0) {
                    Entry<String, JsonValue> nextEntry = iter.next();
                    parsePair(nextEntry.getKey(), nextEntry.getValue());
                }

            } else {

                contentHandler.startElement(Constants.EMPTY_STRING, Constants.EMPTY_STRING, null, attributes.setValue(jsonValue, attributePrefix, namespaces, getNamespaceSeparator(), isNamespaceAware()));

                while (iter.hasNext()) {
                    Entry<String, JsonValue> nextEntry = iter.next();
                    parsePair(nextEntry.getKey(), nextEntry.getValue());
                }
                contentHandler.endElement(Constants.EMPTY_STRING, Constants.EMPTY_STRING, null);
            }
            contentHandler.endDocument();
        } else if (jsonValue.getValueType() == ValueType.ARRAY) {

            SAXUnmarshallerHandler rootContentHandler = null;
            if (getContentHandler() instanceof SAXUnmarshallerHandler) {
                rootContentHandler = (SAXUnmarshallerHandler) getContentHandler();
            }
            JsonArray jsonArray = (JsonArray) jsonValue;

            List<Object> list = new ArrayList<>(jsonArray.size());
            for (JsonValue aJsonArray : jsonArray) {
                parseRoot(aJsonArray);
                if (getContentHandler() instanceof SAXUnmarshallerHandler) {
                    SAXUnmarshallerHandler saxUnmarshallerHandler = (SAXUnmarshallerHandler) contentHandler;
                    list.add(saxUnmarshallerHandler.getObject());
                    saxUnmarshallerHandler.setObject(null);
                } else if (getContentHandler() instanceof UnmarshalRecord) {
                    UnmarshalRecord unmarshalRecord = (UnmarshalRecord) contentHandler;
                    Object unmarshalledObject = unmarshalRecord.getCurrentObject();
                    if (includeRoot && unmarshalClass != null) {
                        if (!(unmarshalledObject instanceof Root)) {
                            Root xmlRoot = unmarshalRecord.createRoot();
                            xmlRoot.setNamespaceURI(unmarshalRecord.getRootElementNamespaceUri());
                            xmlRoot.setLocalName(unmarshalRecord.getLocalName());
                            xmlRoot.setObject(unmarshalledObject);
                            unmarshalledObject = xmlRoot;
                        }
                    }
                    list.add(unmarshalledObject);
                    unmarshalRecord.setCurrentObject(null);
                    unmarshalRecord.setRootElementName(null);
                    unmarshalRecord.setLocalName(null);
                }
            }
            if (getContentHandler() instanceof SAXUnmarshallerHandler) {
                ((SAXUnmarshallerHandler) getContentHandler()).setObject(list);
            } else if (getContentHandler() instanceof UnmarshalRecord) {
                ((UnmarshalRecord) getContentHandler()).setCurrentObject(list);
                ((UnmarshalRecord) getContentHandler()).setRootElementName(Constants.EMPTY_STRING);
                ((UnmarshalRecord) getContentHandler()).setLocalName(Constants.EMPTY_STRING);
                if (rootContentHandler != null) {
                    rootContentHandler.setObject(list);
                }
            }

        } else {
            getContentHandler().startDocument();
            parseValue(jsonValue);
        }
    }

    private void parseValue(JsonValue jsonValue) throws SAXException {
        switch (jsonValue.getValueType()) {
            case STRING: {
                String string = ((JsonString) jsonValue).getString();
                contentHandler.characters(string);
                break;
            }
            case FALSE: {
                contentHandler.characters(FALSE);
                break;
            }
            case TRUE: {
                contentHandler.characters(TRUE);
                break;
            }
            case NUMBER: {
                JsonNumber number = ((JsonNumber) jsonValue);
                contentHandler.characters(number.toString());
                break;
            }
            case OBJECT: {
                Entry<String, JsonValue> xmlValueEntry = null;
                for (Entry<String, JsonValue> nextEntry : ((JsonObject) jsonValue).entrySet()) {
                    if (textWrapper != null && textWrapper.equals(nextEntry.getKey())) {
                        xmlValueEntry = nextEntry;
                    } else {
                        parsePair(nextEntry.getKey(), nextEntry.getValue());
                    }
                }
                //Proceed JSON value mapped to @XmlValue property as a last
                if (xmlValueEntry != null) {
                    parsePair(xmlValueEntry.getKey(), xmlValueEntry.getValue());
                }
                break;
            }
            case ARRAY: {
                for (JsonValue value : (JsonArray) jsonValue) {
                    parseValue(value);
                }
                break;
            }
            case NULL: {
                contentHandler.setNil(true);
                break;
            }
            default:
                throw new IllegalStateException("Unhandled valueType: " + jsonValue.getValueType());
        }
    }

    private void parsePair(String name, JsonValue jsonValue) throws SAXException {
        if (jsonValue == null) {
            return;
        }
        ValueType valueType = jsonValue.getValueType();

        if (valueType == ValueType.ARRAY) {
            JsonArray jsonArray = (JsonArray) jsonValue;
            String parentLocalName = name;

            if (attributePrefix != null && parentLocalName.startsWith(attributePrefix)) {
                // do nothing;
                return;
            }
            String uri = Constants.EMPTY_STRING;
            if (isNamespaceAware() && namespaces != null) {
                if (parentLocalName.length() > 2) {
                    int nsIndex = parentLocalName.indexOf(getNamespaceSeparator(), 1);
                    if (nsIndex > -1) {
                        String prefix = parentLocalName.substring(0, nsIndex);
                        uri = namespaces.resolveNamespacePrefix(prefix);
                    }
                    if (uri == null || uri == Constants.EMPTY_STRING) {
                        uri = namespaces.getDefaultNamespaceURI();
                    } else {
                        parentLocalName = parentLocalName.substring(nsIndex + 1);
                    }
                } else {
                    uri = namespaces.getDefaultNamespaceURI();
                }
            }

            boolean isTextValue;
            int arraySize = jsonArray.size();
            if (arraySize == 0) {
                if (contentHandler instanceof UnmarshalRecord || isUnmarshalRecordWithinAdapter()) {
                    final UnmarshalRecord ur = this.contentHandler instanceof UnmarshalRecord ? (UnmarshalRecord) this.contentHandler : getUnmarshalRecordFromAdapter();
                    XPathNode node = ur.getNonAttributeXPathNode(uri, parentLocalName, parentLocalName, null);
                    if (node != null) {
                        NodeValue nv = node.getNodeValue();
                        if (nv == null && node.getTextNode() != null) {
                            nv = node.getTextNode().getUnmarshalNodeValue();
                        }
                        if (nv != null && nv.isContainerValue()) {
                            ur.getContainerInstance(((ContainerValue) nv));
                        }
                    }
                }
            }
            startCollection();

            XPathFragment groupingXPathFragment = null;
            XPathFragment itemXPathFragment = null;
            if (contentHandler instanceof UnmarshalRecord || isUnmarshalRecordWithinAdapter()) {
                final UnmarshalRecord contentHandler_ = contentHandler instanceof UnmarshalRecord ? (UnmarshalRecord) contentHandler : getUnmarshalRecordFromAdapter();
                isTextValue = isTextValue(parentLocalName, contentHandler_);
                UnmarshalRecord unmarshalRecord = contentHandler_;
                if (unmarshalRecord.getUnmarshaller().isWrapperAsCollectionName()) {
                    XPathNode unmarshalRecordXPathNode = unmarshalRecord.getXPathNode();
                    if (null != unmarshalRecordXPathNode) {
                        XPathFragment currentFragment = new XPathFragment();
                        currentFragment.setLocalName(parentLocalName);
                        currentFragment.setNamespaceURI(uri);
                        currentFragment.setNamespaceAware(isNamespaceAware());
                        XPathNode groupingXPathNode = unmarshalRecordXPathNode.getNonAttributeChildrenMap().get(currentFragment);
                        if (groupingXPathNode != null) {
                            if (groupingXPathNode.getUnmarshalNodeValue() instanceof CollectionGroupingElementNodeValue) {
                                groupingXPathFragment = groupingXPathNode.getXPathFragment();
                                contentHandler_.startElement(uri, parentLocalName, parentLocalName, new AttributesImpl());
                                XPathNode itemXPathNode = groupingXPathNode.getNonAttributeChildren().get(0);
                                itemXPathFragment = itemXPathNode.getXPathFragment();
                            } else if (groupingXPathNode.getUnmarshalNodeValue() == null) {
                                XPathNode itemXPathNode = groupingXPathNode.getNonAttributeChildren().get(0);
                                if (itemXPathNode != null) {
                                    if ((itemXPathNode.getUnmarshalNodeValue()).isContainerValue()) {
                                        groupingXPathFragment = groupingXPathNode.getXPathFragment();
                                        contentHandler_.startElement(uri, parentLocalName, parentLocalName, new AttributesImpl());
                                        itemXPathFragment = itemXPathNode.getXPathFragment();
                                    }
                                }
                            }
                        }
                    }
                }

                for (JsonValue nextArrayValue : jsonArray) {
                    if (nextArrayValue.getValueType() == ValueType.NULL) {
                        contentHandler.setNil(true);
                    }

                    if (!isTextValue) {
                        if (null != itemXPathFragment) {
                            contentHandler.startElement(itemXPathFragment.getNamespaceURI(), itemXPathFragment.getLocalName(), itemXPathFragment.getLocalName(), attributes.setValue(nextArrayValue, attributePrefix, namespaces, getNamespaceSeparator(), isNamespaceAware()));
                        } else {
                            contentHandler.startElement(uri, parentLocalName, parentLocalName, attributes.setValue(nextArrayValue, attributePrefix, namespaces, getNamespaceSeparator(), isNamespaceAware()));
                        }

                    }
                    //Internally store each nested array it as JsonObject with name: "item"
                    if (valueType == nextArrayValue.getValueType()) {
                        JsonBuilderFactory factory = Json.createBuilderFactory(null);
                        JsonObjectBuilder jsonObjectBuilder = factory.createObjectBuilder();
                        jsonObjectBuilder.add("item", nextArrayValue);
                        nextArrayValue = jsonObjectBuilder.build();
                    }
                    parseValue(nextArrayValue);
                    if (!isTextValue) {
                        if (null != itemXPathFragment) {
                            contentHandler.endElement(itemXPathFragment.getNamespaceURI(), itemXPathFragment.getLocalName(), itemXPathFragment.getLocalName());
                        } else {
                            contentHandler.endElement(uri, parentLocalName, parentLocalName);
                        }
                    }
                }
            }
            if (null != groupingXPathFragment) {
                contentHandler.endElement(uri, groupingXPathFragment.getLocalName(), groupingXPathFragment.getLocalName());
            }
            endCollection();
        } else {
            if (attributePrefix != null && name.startsWith(attributePrefix)) {
                return;
            }
            String localName = name;
            String uri = Constants.EMPTY_STRING;
            if (isNamespaceAware() && namespaces != null) {
                if (localName.length() > 2) {
                    int nsIndex = localName.indexOf(getNamespaceSeparator(), 1);
                    String prefix = Constants.EMPTY_STRING;
                    if (nsIndex > -1) {
                        prefix = localName.substring(0, nsIndex);
                    }
                    uri = namespaces.resolveNamespacePrefix(prefix);
                    if (uri == null || uri == Constants.EMPTY_STRING) {
                        uri = namespaces.getDefaultNamespaceURI();
                    } else {
                        localName = localName.substring(nsIndex + 1);
                    }

                    if (localName.equals(Constants.SCHEMA_TYPE_ATTRIBUTE) && uri != null && uri.equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)) {
                        return;
                    }
                } else {
                    uri = namespaces.getDefaultNamespaceURI();
                }
            }
            if (contentHandler instanceof XMLRootRecord || contentHandler instanceof DeferredContentHandler) {
                if (jsonTypeCompatibility) {
                    // if its not namespaceAware don't report the "type" child as it
                    // is will be read by the xsi:type lookup
                    if (!isNamespaceAware() && localName.equals(Constants.SCHEMA_TYPE_ATTRIBUTE)) {
                        return;
                    }
                }
                if (textWrapper != null && textWrapper.equals(localName)) {
                    parseValue(jsonValue);
                    return;
                }
            } else if (contentHandler instanceof UnmarshalRecord && ((UnmarshalRecord) contentHandler).getXPathNode() != null) {
                if (jsonTypeCompatibility) {
                    if (!isNamespaceAware() && localName.equals(Constants.SCHEMA_TYPE_ATTRIBUTE) && !((UnmarshalRecord) contentHandler).getXPathNode().hasTypeChild()) {
                        return;
                    }
                }
                boolean isTextValue = isTextValue(localName, (UnmarshalRecord) contentHandler);
                if (isTextValue) {
                    parseValue(jsonValue);
                    return;
                }
                NodeValue nv = ((UnmarshalRecord) contentHandler).getAttributeChildNodeValue(uri, localName);
                if (attributePrefix == null && nv != null) {
                    return;
                }
            } else if (isUnmarshalRecordWithinAdapter()) {
                @SuppressWarnings("rawtypes") final UnmarshalRecord contentHandler_ = getUnmarshalRecordFromAdapter();
                if (jsonTypeCompatibility) {
                    if (!isNamespaceAware() && localName.equals(Constants.SCHEMA_TYPE_ATTRIBUTE) && !contentHandler_.getXPathNode().hasTypeChild()) {
                        return;
                    }
                }
                boolean isTextValue = isTextValue(localName, contentHandler_);
                if (isTextValue) {
                    parseValue(jsonValue);
                    return;
                }
                NodeValue nv = contentHandler_.getAttributeChildNodeValue(uri, localName);
                if (attributePrefix == null && nv != null) {
                    return;
                }
            }

            if (jsonValue.getValueType() == ValueType.NULL) {
                contentHandler.setNil(true);
            }

            contentHandler.startElement(uri, localName, localName, attributes.setValue(jsonValue, attributePrefix, namespaces, getNamespaceSeparator(), isNamespaceAware()));
            parseValue(jsonValue);
            contentHandler.endElement(uri, localName, localName);

        }

    }

    private UnmarshalRecord getUnmarshalRecordFromAdapter() {
        return (UnmarshalRecord) ((ValidatingContentHandler) ((ExtendedContentHandlerAdapter) contentHandler)
                .getContentHandler()).getContentHandler();
    }

    private boolean isUnmarshalRecordWithinAdapter() {
        return contentHandler instanceof ExtendedContentHandlerAdapter
                && ((ExtendedContentHandlerAdapter) contentHandler)
                .getContentHandler() instanceof ValidatingContentHandler
                && ((ValidatingContentHandler) ((ExtendedContentHandlerAdapter) contentHandler).getContentHandler())
                .getContentHandler() instanceof UnmarshalRecord;
    }

    @Override
    public boolean isNullRepresentedByXsiNil(AbstractNullPolicy nullPolicy) {
        return true;
    }

    private void startCollection() {
        isInCollection = true;
    }

    private void endCollection() {
        isInCollection = false;
    }

    @Override
    public boolean isInCollection() {
        return isInCollection;
    }

    private boolean isTextValue(String localName, UnmarshalRecord contentHandler_) {
        XPathNode currentNode = contentHandler_.getXPathNode();
        if (currentNode == null) {
            return textWrapper != null && textWrapper.equals(localName);
        }

        return ((currentNode.getNonAttributeChildrenMap() == null
                || currentNode.getNonAttributeChildrenMap().size() == 0
                || (currentNode.getNonAttributeChildrenMap().size() == 1
                && currentNode.getTextNode() != null)
        ) && textWrapper != null && textWrapper.equals(localName)
        );
    }


    @Override
    public Object convertValueBasedOnSchemaType(Field xmlField, Object value, ConversionManager conversionManager, AbstractUnmarshalRecord record) {
        if (xmlField.getSchemaType() != null) {
            if (Constants.QNAME_QNAME.equals(xmlField.getSchemaType())) {
                String stringValue = (String) value;
                int indexOpen = stringValue.indexOf('{');
                int indexClose = stringValue.indexOf('}');
                String uri;
                String localName;
                if (indexOpen > -1 && indexClose > -1) {
                    uri = stringValue.substring(indexOpen + 1, indexClose);
                    localName = stringValue.substring(indexClose + 1);
                } else {
                    QName obj = (QName) xmlField.convertValueBasedOnSchemaType(stringValue, conversionManager, record);
                    localName = obj.getLocalPart();
                    uri = obj.getNamespaceURI();
                }
                if (uri != null) {
                    return new QName(uri, localName);
                } else {
                    return new QName(localName);
                }
            } else {
                Class fieldType = xmlField.getType();
                if (fieldType == null) {
                    fieldType = xmlField.getJavaClass(xmlField.getSchemaType(), conversionManager);
                }
                return conversionManager.convertObject(value, fieldType, xmlField.getSchemaType());
            }
        }
        return value;
    }

    /**
     * INTERNAL: The MediaType associated with this reader
     */
    @Override
    public MediaType getMediaType() {
        return Constants.APPLICATION_JSON;
    }

    private static class JsonAttributes extends IndexedAttributeList {

        private JsonValue value;
        private String attributePrefix;
        private char namespaceSeparator;
        private NamespaceResolver namespaces;
        private boolean namespaceAware;

        public JsonAttributes setValue(JsonValue value, String attributePrefix, NamespaceResolver nr, char namespaceSeparator, boolean namespaceAware) {
            reset();
            this.value = value;
            this.attributePrefix = attributePrefix;
            this.namespaces = nr;
            this.namespaceSeparator = namespaceSeparator;
            this.namespaceAware = namespaceAware;
            return this;
        }

        private void addSimpleAttribute(List<Attribute> attributes, String uri, String attributeLocalName, JsonValue childValue) {
            switch (childValue.getValueType()) {
                case STRING: {
                    String stringValue = ((JsonString) childValue).getString();
                    attributes.add(new Attribute(uri, attributeLocalName, attributeLocalName, stringValue));
                    break;
                }
                case NUMBER: {
                    attributes.add(new Attribute(uri, attributeLocalName, attributeLocalName, childValue.toString()));
                    break;
                }
                case FALSE: {
                    attributes.add(new Attribute(uri, attributeLocalName, attributeLocalName, FALSE));
                    break;
                }
                case TRUE: {
                    attributes.add(new Attribute(uri, attributeLocalName, attributeLocalName, TRUE));
                    break;
                }
                case ARRAY:
                case OBJECT:
                case NULL:
                    break; // noop
                default:
                    throw new IllegalStateException("Unhandled valueType: " + childValue.getValueType());
            }
        }

        @Override
        public int getIndex(String uri, String localName) {
            if (null == localName) {
                return -1;
            }
            int index = 0;
            for (Attribute attribute : attributes()) {
                if (namespaceAware) {
                    if (localName.equals(attribute.getLocalName()) && uri.equals(attribute.getUri())) {
                        return index;
                    }
                } else {
                    if (attribute.getName().equals(localName)) {
                        return index;
                    }
                }
                index++;
            }
            return -1;
        }

        @Override
        protected Attribute[] attributes() {
            if (null == attributes) {

                switch (value.getValueType()) {
                    case NULL: {
                        return NO_ATTRIBUTES;
                    }
                    case OBJECT: {
                        JsonObject jsonObject = (JsonObject) value;
                        ArrayList<Attribute> attributesList = new ArrayList<>(jsonObject.values().size());

                        for (Entry<String, JsonValue> nextEntry : jsonObject.entrySet()) {
                            String attributeLocalName = nextEntry.getKey();

                            if (attributePrefix != null) {
                                if (attributeLocalName.startsWith(attributePrefix)) {
                                    attributeLocalName = attributeLocalName.substring(attributePrefix.length());
                                } else {
                                    continue;
                                }
                            }

                            String uri = Constants.EMPTY_STRING;

                            if (namespaceAware && namespaces != null) {
                                if (attributeLocalName.length() > 2) {
                                    String prefix = Constants.EMPTY_STRING;
                                    int nsIndex = attributeLocalName.indexOf(namespaceSeparator, 1);
                                    if (nsIndex > -1) {
                                        prefix = attributeLocalName.substring(0, nsIndex);
                                    }
                                    uri = namespaces.resolveNamespacePrefix(prefix);
                                    if (uri == null) {
                                        uri = namespaces.getDefaultNamespaceURI();
                                    } else {
                                        attributeLocalName = attributeLocalName.substring(nsIndex + 1);
                                    }
                                } else {
                                    uri = namespaces.getDefaultNamespaceURI();
                                }
                            }

                            JsonValue nextValue = nextEntry.getValue();
                            if (nextValue.getValueType() == ValueType.ARRAY) {
                                JsonArray jsonArray = (JsonArray) nextValue;
                                if (jsonArray.size() == 0) {
                                    attributesList.add(new Attribute(uri, attributeLocalName, attributeLocalName, ""));
                                }
                                for (JsonValue nextChildValue : jsonArray) {
                                    addSimpleAttribute(attributesList, uri, attributeLocalName, nextChildValue);
                                }
                            } else {
                                addSimpleAttribute(attributesList, uri, attributeLocalName, nextValue);
                            }
                        }

                        attributes = attributesList.toArray(new Attribute[attributesList.size()]);
                        break;
                    }
                    default: {
                        attributes = NO_ATTRIBUTES;
                    }
                }
            }
            return attributes;
        }

    }

}
