/*
 * 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:
//     bdoughan - Jan 27/2009 - 1.1 - Initial implementation
//     bdoughan - Mar 31/2009 - 2.0 - Added ChangeSummary Support
package org.eclipse.persistence.sdo.helper.jaxb;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import org.eclipse.persistence.core.mappings.CoreAttributeAccessor;
import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.internal.core.helper.CoreField;
import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy;
import org.eclipse.persistence.internal.oxm.MappingNodeValue;
import org.eclipse.persistence.internal.oxm.TreeObjectBuilder;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.XPathNode;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jaxb.JAXBContext;
import org.eclipse.persistence.mappings.ContainerMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.eclipse.persistence.oxm.mappings.XMLInverseReferenceMapping;
import org.eclipse.persistence.oxm.mappings.XMLObjectReferenceMapping;
import org.eclipse.persistence.sdo.SDOChangeSummary;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.ValueStore;
import org.eclipse.persistence.sdo.helper.ListWrapper;

import commonj.sdo.DataObject;
import commonj.sdo.Property;

/**
 * The JAXBValueStore enables a DataObject to access data from a POJO.
 * The link between an SDO property and a POJO property is through their
 * XML representation.  For the POJO property this corresponds to its
 * JAXB mapping.
 */
public class JAXBValueStore implements ValueStore {

    private JAXBHelperContext jaxbHelperContext;
    private Object entity;
    private XMLDescriptor descriptor;
    private SDODataObject dataObject;
    private Map<Property, JAXBListWrapper> listWrappers;

    public JAXBValueStore(JAXBHelperContext aJAXBHelperContext, SDOType sdoType) {
        this.jaxbHelperContext = aJAXBHelperContext;
        this.listWrappers = new WeakHashMap<Property, JAXBListWrapper>();
        this.descriptor = jaxbHelperContext.getObjectDescriptor(sdoType);
        this.entity = this.descriptor.getInstantiationPolicy().buildNewInstance();
    }

    public JAXBValueStore(JAXBHelperContext aJAXBHelperContext, Object anEntity) {
        this.jaxbHelperContext = aJAXBHelperContext;
        this.listWrappers = new WeakHashMap<Property, JAXBListWrapper>();
        JAXBContext jaxbContext = (JAXBContext) jaxbHelperContext.getJAXBContext();
        this.descriptor = (XMLDescriptor) jaxbContext.getXMLContext().getSession(anEntity).getDescriptor(anEntity);
        this.entity = anEntity;
    }

    private JAXBValueStore(JAXBHelperContext aJAXBHelperContext, Object anEntity, XMLDescriptor aDescriptor, SDODataObject aDataObject, Map<Property, JAXBListWrapper> aMap) {
        this.jaxbHelperContext = aJAXBHelperContext;
        this.entity = anEntity;
        this.descriptor = aDescriptor;
        this.dataObject = aDataObject;
        this.listWrappers = aMap;

        for(JAXBListWrapper jaxbListWrapper : listWrappers.values()) {
            jaxbListWrapper.getCurrentElements().setValueStore(this);
        }
    }

    /**
     * Return the DataObject associated with this value store.
     */
    SDODataObject getDataObject() {
        return dataObject;
    }

    /**
     * Return the POJO associated with this value store.
     */
    Object getEntity() {
        return entity;
    }

    /**
     * Return the XMLDescriptor associated with this value store.
     * This is the XMLDescriptor for the associated POJO.
     */
    XMLDescriptor getEntityDescriptor() {
        return descriptor;
    }

    /**
     * Return the JAXBHelperContext.  This is the JAXBHelperContext
     * used to create the DataObject.
     */
    JAXBHelperContext getJAXBHelperContext() {
        return jaxbHelperContext;
    }

    /**
     * Initialize the value store with its associated DataObject.
     */
    @Override
    public void initialize(DataObject aDataObject) {
        this.dataObject = (SDODataObject) aDataObject;
    }

    /**
     * Get the value from the wrapped POJO, wrapping in DataObjects as
     * necessary.
     */
    @Override
    public Object getDeclaredProperty(int propertyIndex) {
        SDOProperty declaredProperty = (SDOProperty) dataObject.getType().getDeclaredProperties().get(propertyIndex);
        if(declaredProperty.getType().isChangeSummaryType()) {
            return dataObject.getChangeSummary();
        }
        Mapping mapping = this.getJAXBMappingForProperty(declaredProperty);
        Object value = mapping.getAttributeAccessor().getAttributeValueFromObject(entity);
        if (declaredProperty.isMany()) {
            JAXBListWrapper listWrapper = listWrappers.get(declaredProperty);
            if (null != listWrapper) {
                return listWrapper;
            }
            listWrapper = new JAXBListWrapper(this, declaredProperty);
            listWrappers.put(declaredProperty, listWrapper);
            return listWrapper;
        } else if(null == value || declaredProperty.getType().isDataType()) {
            return value;
        } else {
            if(declaredProperty.isContainment()) {
                return jaxbHelperContext.wrap(value, declaredProperty, dataObject);
            } else {
                return jaxbHelperContext.wrap(value);
            }
        }
    }

    /**
     * Set the value on the underlying POJO, unwrapping values as necessary.
     */
    @Override
    public void setDeclaredProperty(int propertyIndex, Object value) {
        SDOProperty declaredProperty = (SDOProperty) dataObject.getType().getDeclaredProperties().get(propertyIndex);
        if(declaredProperty.getType().isChangeSummaryType()) {
            return;
        }

        Mapping mapping = this.getJAXBMappingForProperty(declaredProperty);

        Object newValue = value;
        Object oldValue = mapping.getAttributeAccessor().getAttributeValueFromObject(entity);

        if (declaredProperty.getType().isDataType()) {
            if (!declaredProperty.isMany()) {
                AbstractSession session = ((JAXBContext) jaxbHelperContext.getJAXBContext()).getXMLContext().getSession(entity);
                XMLDirectMapping directMapping = (XMLDirectMapping) mapping;
                if (directMapping.hasConverter()) {
                    newValue = directMapping.getConverter().convertDataValueToObjectValue(newValue, session);
                } else {
                    CoreField field = mapping.getField();
                    newValue = session.getDatasourcePlatform().getConversionManager().convertObject(newValue, descriptor.getObjectBuilder().getFieldClassification((XMLField) field));
                }
            }
            mapping.setAttributeValueInObject(entity, newValue);
        } else if (declaredProperty.isMany()) {
            // Get a ListWrapper and set it's current elements
            ListWrapper listWrapper = (ListWrapper) getDeclaredProperty(propertyIndex);
            listWrapper.addAll((List) newValue);
        } else {
            // OLD VALUE
            if (mapping.isAbstractCompositeObjectMapping()) {
                XMLCompositeObjectMapping compositeMapping = (XMLCompositeObjectMapping) mapping;
                XMLInverseReferenceMapping inverseReferenceMapping = compositeMapping.getInverseReferenceMapping();
                if (oldValue != null && inverseReferenceMapping != null && inverseReferenceMapping.getAttributeAccessor() != null) {
                    inverseReferenceMapping.getAttributeAccessor().setAttributeValueInObject(oldValue, null);
                }
            }

            // NEW VALUE
            newValue = jaxbHelperContext.unwrap((DataObject) value);
            mapping.getAttributeAccessor().setAttributeValueInObject(entity, newValue);
            if (mapping.isAbstractCompositeObjectMapping()) {
                XMLCompositeObjectMapping compositeMapping = (XMLCompositeObjectMapping) mapping;
                XMLInverseReferenceMapping inverseReferenceMapping = compositeMapping.getInverseReferenceMapping();
                if (value != null && inverseReferenceMapping != null && inverseReferenceMapping.getAttributeAccessor() != null) {
                    inverseReferenceMapping.getAttributeAccessor().setAttributeValueInObject(newValue, entity);
                }
            }
        }

    }

    /**
     * For isMany=false properties return true if not null. For collection properties
     * return true if the collection is not empty.
     */
    @Override
    public boolean isSetDeclaredProperty(int propertyIndex) {
        SDOProperty declaredProperty = (SDOProperty) dataObject.getType().getDeclaredProperties().get(propertyIndex);
        if(declaredProperty.getType().isChangeSummaryType()) {
            return true;
        }
        Mapping mapping = this.getJAXBMappingForProperty(declaredProperty);
        if (declaredProperty.isMany()) {
            Collection collection = (Collection) mapping.getAttributeAccessor().getAttributeValueFromObject(entity);
            if (null == collection) {
                return false;
            }
            return !collection.isEmpty();
        } else {
            return null != mapping.getAttributeAccessor().getAttributeValueFromObject(entity);
        }
    }

    /**
     * For isMany=false properties set the value to null. For isMany=true set
     * the value to an empty container of the appropriate type.
     */
    @Override
    public void unsetDeclaredProperty(int propertyIndex) {
        SDOProperty declaredProperty = (SDOProperty) dataObject.getType().getDeclaredProperties().get(propertyIndex);
        Mapping mapping = this.getJAXBMappingForProperty(declaredProperty);
        if (declaredProperty.isMany()) {
            ContainerMapping containerMapping = (ContainerMapping) mapping;
            ContainerPolicy containerPolicy = containerMapping.getContainerPolicy();

            // OLD VALUE
            if (mapping.isAbstractCompositeCollectionMapping()) {
                XMLCompositeCollectionMapping compositeMapping = (XMLCompositeCollectionMapping) mapping;
                XMLInverseReferenceMapping inverseReferenceMapping = compositeMapping.getInverseReferenceMapping();
                if (inverseReferenceMapping != null && inverseReferenceMapping.getAttributeAccessor() != null) {

                    Object oldContainer = mapping.getAttributeValueFromObject(entity);
                    if (oldContainer != null) {
                        AbstractSession session = ((JAXBContext) jaxbHelperContext.getJAXBContext()).getXMLContext().getSession(entity);
                        Object iterator = containerPolicy.iteratorFor(oldContainer);
                        while (containerPolicy.hasNext(iterator)) {
                            Object oldValue = containerPolicy.next(iterator, session);
                            inverseReferenceMapping.getAttributeAccessor().setAttributeValueInObject(oldValue, null);
                        }
                    }
                }
            }

            // NEW VALUE
            Object container = containerPolicy.containerInstance();
            mapping.getAttributeAccessor().setAttributeValueInObject(entity, container);
        } else {
            // OLD VALUE
            Object oldValue = mapping.getAttributeAccessor().getAttributeValueFromObject(entity);
            if (mapping.isAbstractCompositeObjectMapping()) {
                XMLCompositeObjectMapping compositeMapping = (XMLCompositeObjectMapping) mapping;
                final XMLInverseReferenceMapping inverseReferenceMapping = compositeMapping.getInverseReferenceMapping();
                if (inverseReferenceMapping != null && inverseReferenceMapping.getAttributeAccessor() != null) {
                    if (oldValue != null) {
                        inverseReferenceMapping.getAttributeAccessor().setAttributeValueInObject(oldValue, null);
                    }
                }
            }

            // NEW VALUE
            mapping.getAttributeAccessor().setAttributeValueInObject(entity, null);
        }
    }

    @Override
    public Object getOpenContentProperty(Property property) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setOpenContentProperty(Property property, Object value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isSetOpenContentProperty(Property property) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void unsetOpenContentProperty(Property property) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setManyProperty(Property property, Object value) {
    }

    @Override
    public ValueStore copy() {
        AbstractSession session = ((JAXBContext) jaxbHelperContext.getJAXBContext()).getXMLContext().getSession(entity);
        Object originalEntity = entity;
        entity = descriptor.getInstantiationPolicy().buildNewInstance();

        for(SDOProperty sdoProperty : (List<SDOProperty>) dataObject.getType().getProperties()) {
            if(!sdoProperty.getType().isChangeSummaryType()) {
                Mapping mapping = getJAXBMappingForProperty(sdoProperty);
                CoreAttributeAccessor attributeAccessor = mapping.getAttributeAccessor();
                Object attributeValue = attributeAccessor.getAttributeValueFromObject(originalEntity);
                if(mapping.isCollectionMapping()) {
                    Object containerCopy = null;
                    SDOChangeSummary sdoChangeSummary = dataObject.getChangeSummary();
                    if(null != sdoChangeSummary) {
                        List list = listWrappers.get(sdoProperty);
                        containerCopy = sdoChangeSummary.getOriginalElements().get(list);
                    }
                    if(null == containerCopy) {
                        CoreContainerPolicy containerPolicy = mapping.getContainerPolicy();
                        containerCopy = containerPolicy.containerInstance();
                        if(null != attributeValue) {
                            Object attributeValueIterator = containerPolicy.iteratorFor(attributeValue);
                            while(containerPolicy.hasNext(attributeValueIterator)) {
                                containerPolicy.addInto(containerPolicy.nextEntry(attributeValueIterator), containerCopy, session);
                            }
                        }
                    }
                    attributeAccessor.setAttributeValueInObject(entity, containerCopy);
                } else {
                    attributeAccessor.setAttributeValueInObject(entity, attributeValue);
                }
            }
        }
        return new JAXBValueStore(jaxbHelperContext, originalEntity, descriptor, dataObject, listWrappers);
    }

    /**
     * Return the JAXB mapping for the SDO property.  They are matched
     * on their XML schema representation.
     */
    Mapping getJAXBMappingForProperty(SDOProperty sdoProperty) {
        DatabaseMapping sdoMapping = sdoProperty.getXmlMapping();
        XMLField field;
        if (sdoMapping instanceof XMLObjectReferenceMapping) {
            XMLObjectReferenceMapping referenceMapping = (XMLObjectReferenceMapping) sdoMapping;
            field = (XMLField) referenceMapping.getFields().get(0);
        } else {
            field = (XMLField) sdoMapping.getField();
        }
        TreeObjectBuilder treeObjectBuilder = (TreeObjectBuilder) descriptor.getObjectBuilder();
        XPathNode xPathNode = treeObjectBuilder.getRootXPathNode();
        XPathFragment xPathFragment = field.getXPathFragment();
        while (xPathNode != null && xPathFragment != null) {
            if (xPathFragment.isAttribute()) {
                if (sdoProperty.isMany() && !sdoProperty.isContainment() && !sdoProperty.getType().isDataType()) {
                    xPathFragment = null;
                    break;
                }
                Map attributeChildrenMap = xPathNode.getAttributeChildrenMap();
                if (null == attributeChildrenMap) {
                    xPathNode = null;
                } else {
                    xPathNode = (XPathNode) attributeChildrenMap.get(xPathFragment);
                }
            } else if (xPathFragment.nameIsText()) {
                xPathNode = xPathNode.getTextNode();
            } else {
                Map nonAttributeChildrenMap = xPathNode.getNonAttributeChildrenMap();
                if (null == nonAttributeChildrenMap) {
                    xPathNode = null;
                } else {
                    xPathNode = (XPathNode) nonAttributeChildrenMap.get(xPathFragment);
                }
            }
            xPathFragment = xPathFragment.getNextFragment();
            if (xPathFragment != null && xPathFragment.nameIsText()) {
                if (sdoProperty.isMany() && !sdoProperty.isContainment()) {
                    xPathFragment = null;
                    break;
                }
            }
        }
        if (null == xPathFragment && xPathNode != null) {
            if (xPathNode.getNodeValue().isMappingNodeValue()) {
                MappingNodeValue mappingNodeValue = (MappingNodeValue) xPathNode.getNodeValue();
                return mappingNodeValue.getMapping();
            }
        }
        throw SDOException.sdoJaxbNoMappingForProperty(sdoProperty.getName(), field.getXPath());
    }

}
