/*
 * 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:
//     Matt MacIvor - 2.5.1 - Initial Implementation
package org.eclipse.persistence.oxm.mappings;

import java.util.Vector;

import javax.xml.namespace.QName;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor;
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.VariableXPathCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.XMLContainerMapping;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.queries.MapContainerPolicy;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.AttributeAccessor;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.record.XMLRecord;
import org.eclipse.persistence.sessions.Session;
public class XMLVariableXPathCollectionMapping extends XMLCompositeCollectionMapping implements VariableXPathCollectionMapping<AbstractSession, AttributeAccessor, ContainerPolicy, Converter, ClassDescriptor, DatabaseField, XMLMarshaller, Session, XMLUnmarshaller, XMLRecord>, XMLMapping, XMLContainerMapping {

    protected String variableAttributeName;
    protected String variableGetMethodName;
    protected String variableSetMethodName;

    private AttributeAccessor variableAttributeAccessor;

    private boolean isAttribute;

    /**
     * Default constructor.
     */
    public XMLVariableXPathCollectionMapping() {
        super();
    }

    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
       super.initialize(session);

        if(variableAttributeAccessor == null){

            if(variableAttributeName != null){
                this.variableAttributeAccessor = new InstanceVariableAttributeAccessor();
                this.variableAttributeAccessor.setAttributeName(variableAttributeName);
            }else if(variableGetMethodName != null){
                this.variableAttributeAccessor = new MethodAttributeAccessor();
                this.variableAttributeAccessor.setAttributeName("VARIABLE");
                ((MethodAttributeAccessor)this.variableAttributeAccessor).setGetMethodName(variableGetMethodName);
                if(variableSetMethodName == null){
                    this.variableAttributeAccessor.setIsWriteOnly(true);
                }else{
                    ((MethodAttributeAccessor)this.variableAttributeAccessor).setSetMethodName(variableSetMethodName);
                }
            }
        }
        this.variableAttributeAccessor.initializeAttributes(this.getReferenceClass());
    }

    public void useMapClass(String concreteContainerClassName) {
        MapContainerPolicy policy = new MapContainerPolicy(concreteContainerClassName);
        this.setContainerPolicy(policy);
    }

    @Override
    protected void initializeMapContainerPolicy(AbstractSession session, MapContainerPolicy cp){
           super.initializeMapContainerPolicy(session, cp);
           if(variableAttributeName != null){
               cp.setKeyName(variableAttributeName);
           }else if(variableGetMethodName != null){
               cp.setKeyMethodName(variableGetMethodName);
           }
       }

    @Override
    protected Vector collectFields() {
        if(field != null){
            return super.collectFields();
        }
       // Vector fields = new Vector(1);
        //fields.addElement(this.getField());
        //return fields;
        return NO_FIELDS;
    }

@Override
public Vector getFields() {
    return collectFields();
}

//    public Vector getFields() {
  //      return fields;
        //return NO_FIELDS;
    // }

    @Override
    protected void initializeReferenceDescriptorAndField(AbstractSession session){
         if (getReferenceClass() == null) {
             throw DescriptorException.referenceClassNotSpecified(this);
         }

         setReferenceDescriptor(session.getDescriptor(getReferenceClass()));


         ClassDescriptor refDescriptor = this.getReferenceDescriptor();
         if (refDescriptor == null) {
             session.getIntegrityChecker().handleError(DescriptorException.descriptorIsMissing(getReferenceClass().getName(), this));
             return;
         }

         if(field != null){
           setField(getDescriptor().buildField(this.field));
           setFields(collectFields());
         }

         if (hasConverter()) {
             getConverter().initialize(this, session);
         }
   }

    @Override
    public boolean isAbstractCompositeCollectionMapping(){
        return false;
    }

    public String getVariableAttributeName() {
        return variableAttributeName;
    }

    @Override
    public void setVariableAttributeName(String variableAttributeName) {
        this.variableAttributeName = variableAttributeName;
    }

    public String getVariableGetMethodName() {
        return variableGetMethodName;
    }

    @Override
    public void setVariableGetMethodName(String variableGetMethodName) {
        this.variableGetMethodName = variableGetMethodName;
    }

    public String getVariableSetMethodName() {
        return variableSetMethodName;
    }

    @Override
    public void setVariableSetMethodName(String variableSetMethodName) {
        this.variableSetMethodName = variableSetMethodName;
    }


    @Override
    public AttributeAccessor getVariableAttributeAccessor() {
        return variableAttributeAccessor;
    }

    @Override
    public void setVariableAttributeAccessor(
            AttributeAccessor variableAttributeAccessor) {
        this.variableAttributeAccessor = variableAttributeAccessor;
    }


     @Override
    public void writeFromObjectIntoRow(Object object, AbstractRecord row, AbstractSession session, WriteType writeType) throws DescriptorException {
          if (this.isReadOnly()) {
                return;
            }

            Object attributeValue = this.getAttributeValueFromObject(object);
            ContainerPolicy cp = this.getContainerPolicy();

            Object iter = cp.iteratorFor(attributeValue);
            if(null != iter) {
                while(cp.hasNext(iter)) {
                    Object element = cp.next(iter, session);
                    // convert the value - if necessary
                    element = convertObjectValueToDataValue(element, session, ((XMLRecord) row).getMarshaller());
                    if(element != null) {
                        XMLField variableField = new XMLField();
                        XMLRecord xmlRow = (XMLRecord)row;
                        //variableField.setXPathFragment(getXPathFragmentForValue(element,(XMLRecord)row));
                        variableField.setXPathFragment(getXPathFragmentForValue(element,xmlRow.getNamespaceResolver(), xmlRow.isNamespaceAware(), xmlRow.getNamespaceSeparator()));
                        row.put(variableField, buildCompositeRow(variableField, element, session, row, writeType));
                    }
                }
            }
     }

     protected AbstractRecord buildCompositeRow(XMLField variableField, Object attributeValue, AbstractSession session, AbstractRecord parentRow, WriteType writeType) {
         ClassDescriptor  classDesc = getReferenceDescriptor(attributeValue, session);
         return buildCompositeRowForDescriptor(classDesc, attributeValue, session, (XMLRecord)parentRow, writeType);
    }

     @Override
    public XPathFragment getXPathFragmentForValue(Object obj, NamespaceResolver nr, boolean isNamespaceAware,char sep) {
            Object value = getVariableAttributeAccessor().getAttributeValueFromObject(obj);
            if(value == null){
                throw XMLMarshalException.nullValueNotAllowed(getVariableAttributeName(), getReferenceClassName());
            }

            String returnString;
            String uri = null;
            if(value instanceof QName){
                returnString = ((QName)value).getLocalPart();
                uri = ((QName)value).getNamespaceURI();
            }else{
                returnString = (String)value;
            }
            XPathFragment frag = new XPathFragment();
            frag.setLocalName(returnString);
            if(isNamespaceAware && uri != null && uri.length() >0){
                String prefix = nr.resolveNamespaceURI(uri);
                if(prefix == null){
                       prefix = nr.generatePrefix();
                    //marshalRecord.namespaceDeclaration(prefix, uri);
                       frag.setGeneratedPrefix(true);
                }
                if(prefix != null && prefix.length() >0){
                    frag.setPrefix(prefix);
                    //returnString = prefix + sep + returnString;
                }
            }

            //frag.setXPath(returnString);
            //frag.setLocalName(localName);

            frag.setNamespaceURI(uri);

            return frag;
        }

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

        @Override
        public void setAttribute(boolean isAttribute) {
            this.isAttribute = isAttribute;
        }

        @Override
        public void useMapClassName(String concreteContainerClassName, String methodName) {
            // the reference class has to be specified before coming here
            if (this.getReferenceClassName() == null) {
                throw DescriptorException.referenceClassNotSpecified(this);
            }
            MapContainerPolicy policy = new MapContainerPolicy(concreteContainerClassName);
            policy.setKeyName(methodName, getReferenceClass().getName());
            this.setContainerPolicy(policy);
        }
}
