/*
 * Copyright (c) 1998, 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:
//     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.
     *
     */
    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;
    }

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

}
