/*
 * Copyright (c) 1998, 2019 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.oxm;


import javax.xml.namespace.QName;

import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.CollectionReferenceMapping;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.record.MarshalContext;
import org.eclipse.persistence.internal.oxm.record.MarshalRecord;
import org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;
import org.xml.sax.Attributes;

/**
 * INTERNAL:
 * <p><b>Purpose</b>: Class to handle (un)marshal operations for
 * XMLCollectionReferenceMappings.</p>
 *
 * <p>An instance of this class is required for each XMLField set on the
 * mapping, that is, for each source field in the source-target key field
 * association list.</p>
 *
 * <p>When unmarshalling, an instance of org.eclipse.persistence.internal.oxm.Reference is
 * created on a per mapping basis (keyed on source object instance) and sorted
 * on the associated session's org.eclipse.persistence.internal.oxm.ReferenceResolver
 * instance.  Each target primary key value is stored in the Reference instance
 * for use during mapping resolution phase after unmarshalling completes.</p>
 *
 * <p>When marshalling, the target object's primary key value that is mapped to
 * this NodeValue's XMLField (in the XMLObjectReferenceMapping's source-target
 * key field association list) is retrieved and written out.</p>
 *
 * @see org.eclipse.persistence.internal.oxm.Reference
 * @see org.eclipse.persistence.internal.oxm.ReferenceResolver
 * @see org.eclipse.persistence.oxm.mappings.XMLObjectReferenceMapping
 */

public class XMLCollectionReferenceMappingNodeValue extends MappingNodeValue implements ContainerValue {
    private CollectionReferenceMapping xmlCollectionReferenceMapping;
    private Field xmlField;
    private static final String SPACE = " ";
    private int index = -1;

    /**
     * This constructor sets the XMLCollectionReferenceMapping and XMLField members to
     * the provided values.
     *
     * @param xmlCollectionReferenceMapping
     */
    public XMLCollectionReferenceMappingNodeValue(CollectionReferenceMapping xmlCollectionReferenceMapping, Field xmlField) {
        super();
        this.xmlCollectionReferenceMapping = xmlCollectionReferenceMapping;
        this.xmlField = xmlField;
    }

    /**
     * Handle attribute operation.  Here we will create and populate an
     * org.eclipse.persistence.internal.oxm.Reference instance to be used during
     * the mapping resolution stage.  In particular, the primary key value
     * for this element will be added to the Reference object's map of
     * target primary key values - based on the target key field name.  Note
     * that if a reference already exists for the xmlCollectionReferenceMapping's
     * source object instance, we will simply add to the target pk value list.
     * The Reference object is stored on the ReferenceResolver associated with
     * the UnmarshalRecord's session.
     */
    @Override
    public void attribute(UnmarshalRecord unmarshalRecord, String namespaceURI, String localName, String value) {
        if (value != null) {
            Object realValue = unmarshalRecord.getXMLReader().convertValueBasedOnSchemaType(xmlField, value, (ConversionManager) unmarshalRecord.getSession().getDatasourcePlatform().getConversionManager(), unmarshalRecord);
            Object container = unmarshalRecord.getContainerInstance(this);
            // build a reference which will be resolved after unmarshalling is complete
            xmlCollectionReferenceMapping.buildReference(unmarshalRecord, xmlField, realValue, unmarshalRecord.getSession(), container);
        }
    }

    /**
     * Handle endElement operation.  Here we will create and populate an
     * org.eclipse.persistence.internal.oxm.Reference instance to be used during
     * the mapping resolution stage.  In particular, the primary key value
     * for this element will be added to the Reference object's map of
     * target primary key values - based on the target key field name.  Note
     * that if a reference already exists for the xmlCollectionReferenceMapping's
     * source object instance, we will simply add to the target pk value list.
     * The Reference object is stored on the ReferenceResolver associated with
     * the UnmarshalRecord's session.
     */
    @Override
    public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
        if (!xmlField.getLastXPathFragment().nameIsText()) {
            return;
        }

        Object value = unmarshalRecord.getCharacters().toString();
        unmarshalRecord.resetStringBuffer();

        ConversionManager conversionManager = unmarshalRecord.getConversionManager();
        if (unmarshalRecord.getTypeQName() != null) {
            Class typeClass = xmlField.getJavaClass(unmarshalRecord.getTypeQName(), conversionManager);
            value = conversionManager.convertObject(value, typeClass, unmarshalRecord.getTypeQName());
        } else {
            value = unmarshalRecord.getXMLReader().convertValueBasedOnSchemaType(xmlField, value, conversionManager, unmarshalRecord);
        }

        Object container = unmarshalRecord.getContainerInstance(this);

        // build a reference which will be resolved after unmarshalling is complete
        xmlCollectionReferenceMapping.buildReference(unmarshalRecord, xmlField, value, unmarshalRecord.getSession(), container);
    }

    @Override
    public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Object container) {
        this.endElement(xPathFragment, unmarshalRecord);
    }

    /**
     * Indicate if the next XPathFragment is an attribute or text() node.
     */
    @Override
    public boolean isOwningNode(XPathFragment xPathFragment) {
        if(isMarshalNodeValue()) {
            if (xmlCollectionReferenceMapping.usesSingleNode()) {
                return xPathFragment.nameIsText() || xPathFragment.isAttribute();
            }
            XPathFragment nextFragment = xPathFragment.getNextFragment();
            return (nextFragment != null) && (nextFragment.nameIsText() || nextFragment.isAttribute());
        }
        return super.isOwningNode(xPathFragment);
    }

    @Override
    public boolean isWrapperAllowedAsCollectionName() {
        return true;
    }

    @Override
    public boolean isContainerValue() {
        return true;
    }

    @Override
    public Object getContainerInstance() {
        return getContainerPolicy().containerInstance();
    }

    @Override
    public void setContainerInstance(Object object, Object containerInstance) {
        xmlCollectionReferenceMapping.setAttributeValueInObject(object, containerInstance);
    }

    @Override
    public CoreContainerPolicy getContainerPolicy() {
        return xmlCollectionReferenceMapping.getContainerPolicy();
    }

    /**
     * Handle the marshal operation for this NodeValue.  Each of the target
     * object's primary key values that are mapped to the collection mapping's fields
     * (in the XMLCollectionReferenceMapping's source-target key field association list)
     * are retrieved and written out.
     */
    @Override
    public boolean marshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, CoreAbstractSession session, NamespaceResolver namespaceResolver) {
        if(this.xmlCollectionReferenceMapping.isReadOnly()) {
            return false;
        }
        CoreContainerPolicy cp = xmlCollectionReferenceMapping.getContainerPolicy();
        Object collection = xmlCollectionReferenceMapping.getAttributeAccessor().getAttributeValueFromObject(object);
        if (collection == null) {
            return false;
        }

        Object iterator = cp.iteratorFor(collection);
        if (cp.hasNext(iterator)) {
            XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver);
            marshalRecord.closeStartGroupingElements(groupingFragment);
        } else {
            return marshalRecord.emptyCollection(xPathFragment, namespaceResolver, false);
        }
        Object objectValue;

        if (xmlCollectionReferenceMapping.usesSingleNode()) {
            StringBuilder stringValueStringBuilder = new StringBuilder();
            String newValue;
            QName schemaType;
            while (cp.hasNext(iterator)) {
                objectValue = cp.next(iterator, session);
                Object fieldValue = xmlCollectionReferenceMapping.buildFieldValue(objectValue, xmlField, session);
                if (fieldValue == null) {
                    if(null != objectValue) {
                        Field fkField = (Field) xmlCollectionReferenceMapping.getSourceToTargetKeyFieldAssociations().get(xmlField);
                        fieldValue = marshalRecord.getMarshaller().getContext().getValueByXPath(objectValue, fkField.getXPath(), fkField.getNamespaceResolver(), Object.class);
                    }
                    if(null == fieldValue) {
                        break;
                    }
                }
                schemaType = xmlField.getSchemaTypeForValue(fieldValue, session);
                newValue = marshalRecord.getValueToWrite(schemaType, fieldValue, (ConversionManager) session.getDatasourcePlatform().getConversionManager());
                if (newValue != null) {
                    stringValueStringBuilder.append(newValue);
                    if (cp.hasNext(iterator)) {
                        stringValueStringBuilder.append(SPACE);
                    }
                }
            }
            marshalSingleValue(xPathFragment, marshalRecord, object, stringValueStringBuilder.toString(), session, namespaceResolver, ObjectMarshalContext.getInstance());
        } else {
            marshalRecord.startCollection();
            while (cp.hasNext(iterator)) {
                objectValue = cp.next(iterator, session);
                marshalSingleValue(xPathFragment, marshalRecord, object, objectValue, session, namespaceResolver, ObjectMarshalContext.getInstance());
            }
            marshalRecord.endCollection();
        }
        return true;
    }

    /**
     * @param xPathFragment
     * @param unmarshalRecord
     * @param atts
     */
    @Override
    public boolean startElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord, Attributes atts) {
        if (xmlField.getLastXPathFragment().isAttribute()) {
            if (!this.xmlCollectionReferenceMapping.usesSingleNode()) {
                String namespaceURI = xmlField.getLastXPathFragment().getNamespaceURI();
                String value;
                if (namespaceURI == null) {
                    value = atts.getValue(xmlField.getLastXPathFragment().getLocalName());
                } else {
                    value = atts.getValue(namespaceURI, xmlField.getLastXPathFragment().getLocalName());
                }

                xmlCollectionReferenceMapping.buildReference(unmarshalRecord, xmlField, value, unmarshalRecord.getSession(), unmarshalRecord.getContainerInstance(this));
                return true;
            }
        }
        return true;
    }

    @Override
    public boolean marshalSingleValue(XPathFragment xPathFragment, MarshalRecord marshalRecord, Object object, Object value, CoreAbstractSession session, NamespaceResolver namespaceResolver, MarshalContext marshalContext) {
        if (xmlCollectionReferenceMapping.usesSingleNode()) {
            XPathFragment groupingFragment = marshalRecord.openStartGroupingElements(namespaceResolver);
            if (xPathFragment.isAttribute()) {
                marshalRecord.attribute(xPathFragment, namespaceResolver, value, null);
                marshalRecord.closeStartGroupingElements(groupingFragment);
            } else {
                marshalRecord.closeStartGroupingElements(groupingFragment);
                marshalRecord.characters(null, value, null, false);
            }
        } else {
            QName schemaType;
            Object fieldValue = xmlCollectionReferenceMapping.buildFieldValue(value, xmlField, session);
            if (fieldValue == null) {
                return false;
            }
            schemaType = xmlField.getSchemaTypeForValue(fieldValue, session);

            marshalRecord.openStartElement(xPathFragment, namespaceResolver);
            XPathFragment nextFragment = xPathFragment.getNextFragment();
            if (nextFragment.isAttribute()) {
                marshalRecord.attribute(nextFragment, namespaceResolver, fieldValue, schemaType);
                marshalRecord.closeStartElement();
            } else {
                marshalRecord.predicateAttribute(xPathFragment, namespaceResolver);
                marshalRecord.closeStartElement();
                marshalRecord.characters(schemaType, fieldValue, null, false);
            }
            marshalRecord.endElement(xPathFragment, namespaceResolver);
        }
        return true;
    }

    @Override
    public CollectionReferenceMapping getMapping() {
        return xmlCollectionReferenceMapping;
    }

    @Override
    public boolean getReuseContainer() {
        return getMapping().getReuseContainer();
    }

    @Override
    public boolean isMarshalNodeValue() {
        return xmlCollectionReferenceMapping.getFields().size() == 1 || xmlCollectionReferenceMapping.usesSingleNode();
    }

    /**
     *  INTERNAL:
     *  Used to track the index of the corresponding containerInstance in the containerInstances Object[] on UnmarshalRecord
     */
    @Override
    public void setIndex(int index){
        this.index = index;
    }

    /**
     * INTERNAL:
     * Set to track the index of the corresponding containerInstance in the containerInstances Object[] on UnmarshalRecord
     * Set during TreeObjectBuilder initialization
     */
    @Override
    public int getIndex(){
        return index;
    }

    /**
     * INTERNAL
     * Return true if an empty container should be set on the object if there
     * is no presence of the collection in the XML document.
     * @since EclipseLink 2.3.3
     */
    @Override
    public boolean isDefaultEmptyContainer() {
        return getMapping().isDefaultEmptyContainer();
    }

}
