/*
 * Copyright (c) 2012, 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:
//     Blaise Doughan - 2.5 - initial implementation
package org.eclipse.persistence.internal.oxm;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import javax.xml.namespace.QName;

import org.eclipse.persistence.core.mappings.CoreMapping;
import org.eclipse.persistence.core.sessions.CoreProject;
import org.eclipse.persistence.core.sessions.CoreSession;
import org.eclipse.persistence.core.sessions.CoreSessionEventListener;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.databaseaccess.CorePlatform;
import org.eclipse.persistence.internal.core.descriptors.CoreObjectBuilder;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;

public abstract class Context<
    ABSTRACT_SESSION extends CoreAbstractSession,
    DESCRIPTOR extends Descriptor<?, ?, ?, ?, ?, NAMESPACE_RESOLVER, ?, ?, ?, ?>,
    FIELD extends Field,
    NAMESPACE_RESOLVER extends NamespaceResolver,
    PROJECT extends CoreProject,
    SESSION extends CoreSession,
    SESSION_EVENT_LISTENER extends CoreSessionEventListener> {

    public static class ContextState<
        ABSTRACT_SESSION extends CoreAbstractSession,
        DESCRIPTOR extends Descriptor,
        PROJECT extends CoreProject,
        SESSION extends CoreSession,
        SESSION_EVENT_LISTENER extends CoreSessionEventListener> {

        protected Context context;
        protected Map<XPathQName, DESCRIPTOR> descriptorsByQName;
        protected Map<XPathFragment, DESCRIPTOR> descriptorsByGlobalType;
        protected SESSION session;
        private Collection<SESSION_EVENT_LISTENER> sessionEventListeners;

        protected ContextState() {
            descriptorsByQName = new HashMap<>();
            descriptorsByGlobalType = new HashMap<>();
        }

        protected ContextState(Context context, PROJECT project, ClassLoader classLoader, Collection<SESSION_EVENT_LISTENER> sessionEventListeners) {
            this();
            this.context = context;
            preLogin(project, classLoader);
            session = (SESSION) project.createDatabaseSession();

            // if an event listener was passed in as a parameter, register it with the event manager
            if (sessionEventListeners != null) {
                for(SESSION_EVENT_LISTENER sessionEventListener : sessionEventListeners) {
                    session.getEventManager().addListener(sessionEventListener);
                }
            }

            setupSession(session);
            storeDescriptorsByQName(session);
        }

        public void addDescriptorByQName(QName qName, DESCRIPTOR descriptor) {
            XPathQName xpathQName = new XPathQName(qName, true);
            addDescriptorByQName(xpathQName, descriptor);
        }

        private void addDescriptorByQName(XPathQName qName, DESCRIPTOR descriptor) {
            descriptorsByQName.put(qName, descriptor);
        }

        protected void preLogin(PROJECT project, ClassLoader classLoader) {
        }

        /**
         * INTERNAL: Return the Descriptor with the default root mapping matching
         * the QName parameter.
         */
        private DESCRIPTOR getDescriptor(QName qName) {
            XPathQName xpathQName = new XPathQName(qName, true);
            return descriptorsByQName.get(xpathQName);
        }

        /**
         * INTERNAL: Return the Descriptor with the default root mapping matching
         * the QName parameter.
         */
        private DESCRIPTOR getDescriptor(XPathQName qName) {
            return descriptorsByQName.get(qName);
        }

        /**
         * INTERNAL: Return the Descriptor mapped to the global type matching the
         * XPathFragment parameter.
         */
        private DESCRIPTOR getDescriptorByGlobalType(XPathFragment xPathFragment) {
            return this.descriptorsByGlobalType.get(xPathFragment);
        }

        protected SESSION getSession() {
            return session;
        }

        /**
         * INTERNAL: Return the session corresponding to this class. Since the class
         * may be mapped by more that one of the projects used to create the
         * Context, this method will return the first match.
         */
        protected ABSTRACT_SESSION getSession(Class<?> clazz) {
            if (null == clazz) {
                return null;
            }
            if (session.getDescriptor(clazz) != null) {
                return (ABSTRACT_SESSION) session;
            }
            throw XMLMarshalException.descriptorNotFoundInProject(clazz.getName());
        }

        /**
         * INTERNAL: Return the session corresponding to this Descriptor. Since
         * the class may be mapped by more that one of the projects used to create
         * the Context, this method will return the first match.
         */
        protected ABSTRACT_SESSION getSession(DESCRIPTOR descriptor) {
            if (null == descriptor) {
                return null;
            }
            if (session.getProject().getOrderedDescriptors().contains(descriptor)) {
                return (ABSTRACT_SESSION) session;
            }
            throw XMLMarshalException.descriptorNotFoundInProject(descriptor.getJavaClass().getName());
        }

        /**
         * INTERNAL: Return the session corresponding to this object. Since the
         * object may be mapped by more that one of the projects used to create the
         * Context, this method will return the first match.
         */
        protected ABSTRACT_SESSION getSession(Object object) {
            if (null == object) {
                return null;
            }
            if (session.getDescriptor(object) != null) {
                return (ABSTRACT_SESSION) session;
            }
            throw XMLMarshalException.descriptorNotFoundInProject(object.getClass().getName());
        }

        protected void setupSession(SESSION session) {
        }

        /**
         * INTERNAL:
         */
        public void storeDescriptorByQName(DESCRIPTOR descriptor, CorePlatform platform, Set<DESCRIPTOR> processedDescriptors) {
            XPathQName descriptorQName;
            String defaultRootName;

            if (processedDescriptors == null) {
                processedDescriptors = new HashSet<>();
            }

            if (processedDescriptors.contains(descriptor)) {
                return;
            } else {
                processedDescriptors.add(descriptor);
                if (descriptor.hasInheritance() && !descriptor.getInheritancePolicy().isRootParentDescriptor()) {
                    //this means we have a descriptor that is a child in an inheritance hierarchy
                    storeDescriptorByQName((DESCRIPTOR) descriptor.getInheritancePolicy().getParentDescriptor(), platform, processedDescriptors);
                }
            }

            List tableNames = descriptor.getTableNames();
            for (int i = 0; i < tableNames.size(); i++) {
                defaultRootName = (String) tableNames.get(i);

                if (null != defaultRootName) {
                    int index = defaultRootName.indexOf(':');
                    String defaultRootLocalName = defaultRootName.substring(index + 1);
                    if (!defaultRootLocalName.isEmpty()) {
                        if (index > -1) {
                            String defaultRootPrefix = defaultRootName.substring(0, index);
                            String defaultRootNamespaceURI = descriptor.getNamespaceResolver().resolveNamespacePrefix(defaultRootPrefix);
                            descriptorQName = new XPathQName(defaultRootNamespaceURI, defaultRootLocalName, true);
                        } else {
                            if(descriptor.getNamespaceResolver() != null) {
                                descriptorQName = new XPathQName(descriptor.getNamespaceResolver().getDefaultNamespaceURI(), defaultRootLocalName, true);
                            } else {
                                descriptorQName = new XPathQName(defaultRootLocalName, true);
                            }
                        }
                        if (!descriptor.hasInheritance() || descriptor.getInheritancePolicy().isRootParentDescriptor()) {
                            addDescriptorByQName(descriptorQName, descriptor);
                        } else {
                            Descriptor existingDescriptor = getDescriptor(descriptorQName);
                            if (existingDescriptor == null) {
                                addDescriptorByQName(descriptorQName, descriptor);
                            }
                        }
                    }
                }
            }

            XMLSchemaReference xmlSchemaReference = descriptor.getSchemaReference();
            if (null != xmlSchemaReference) {
                String schemaContext = xmlSchemaReference.getSchemaContext();
                if ((xmlSchemaReference.getType() == XMLSchemaReference.COMPLEX_TYPE) || (xmlSchemaReference.getType() == XMLSchemaReference.SIMPLE_TYPE)) {
                    if ((null != schemaContext) && (schemaContext.lastIndexOf('/') == 0)) {
                        schemaContext = schemaContext.substring(1, schemaContext.length());
                        XPathFragment typeFragment = new XPathFragment(schemaContext);
                        if (null != descriptor.getNamespaceResolver()) {
                           String uri = descriptor.getNamespaceResolver().resolveNamespacePrefix(typeFragment.getPrefix());
                           if(uri == null && xmlSchemaReference.getSchemaContextAsQName() != null){
                               uri = xmlSchemaReference.getSchemaContextAsQName().getNamespaceURI();
                           }
                           typeFragment.setNamespaceURI(uri);
                        }
                        this.descriptorsByGlobalType.put(typeFragment, descriptor);
                    } else {
                        QName qname = xmlSchemaReference.getSchemaContextAsQName();
                        if (qname != null) {
                            if (descriptor.isWrapper() && descriptor.getJavaClassName().contains("ObjectWrapper")) {
                                return;
                            }
                            XPathFragment typeFragment = new XPathFragment();
                            typeFragment.setLocalName(qname.getLocalPart());
                            typeFragment.setNamespaceURI(qname.getNamespaceURI());
                            this.descriptorsByGlobalType.put(typeFragment, descriptor);
                        }
                    }
                }
            }
        }

        public void storeDescriptorsByQName(CoreSession session) {
            Iterator iterator = session.getProject().getOrderedDescriptors().iterator();
            Set<DESCRIPTOR> processedDescriptors = new HashSet<>();
            while (iterator.hasNext()) {
                DESCRIPTOR descriptor = (DESCRIPTOR) iterator.next();
                storeDescriptorByQName(descriptor, session.getDatasourcePlatform(), processedDescriptors);
            }
        }

    }

    private static class XPathQueryResult {
        /*
         * Mapping corresponding to the XPath query
         */
        private CoreMapping mapping;

        /*
         * Mapping's owning object
         */
        private Object owner;

        /*
         * Index into mapping, from XPath query (may be null)
         */
        private Integer index;
    }

    protected volatile ContextState<ABSTRACT_SESSION, DESCRIPTOR, PROJECT, SESSION, SESSION_EVENT_LISTENER> contextState;

    private <T> T createByXPath(Object object, CoreObjectBuilder objectBuilder, StringTokenizer stringTokenizer, NAMESPACE_RESOLVER namespaceResolver, Class<T> returnType) {
        XPathQueryResult queryResult = getMappingForXPath(object, objectBuilder, stringTokenizer, namespaceResolver);

        if (null != queryResult.mapping) {
            DESCRIPTOR refDescriptor = (DESCRIPTOR) queryResult.mapping.getReferenceDescriptor();
            if (null != refDescriptor) {
                return (T) refDescriptor.getInstantiationPolicy().buildNewInstance();
            }
        }
        return null;
    }

    /**
     * Create a new object instance for a given XPath, relative to the parentObject.
     *
     * @param <T>
     *      The return type of this method corresponds to the returnType parameter.
     * @param parentObject
     *      The XPath will be executed relative to this object.
     * @param xPath
     *      The XPath statement.
     * @param namespaceResolver
     *      A NamespaceResolver containing the prefix/URI pairings from the XPath statement.
     * @param returnType
     *      The return type.
     *
     * @return
     *      An instance of the Java class mapped to the supplied return type, or null
     *      if no result was found.
     */
    public <T> T createByXPath(Object parentObject, String xPath, NAMESPACE_RESOLVER namespaceResolver, Class<T> returnType) {
        ABSTRACT_SESSION session = this.getSession(parentObject);
        DESCRIPTOR descriptor = (DESCRIPTOR) session.getDescriptor(parentObject);
        StringTokenizer stringTokenizer = new StringTokenizer(xPath, "/");
        return createByXPath(parentObject, descriptor.getObjectBuilder(), stringTokenizer, namespaceResolver, returnType);
    }

    protected abstract FIELD createField(String path);

    public abstract Marshaller createMarshaller();

    public abstract Unmarshaller createUnmarshaller();

    /**
     * INTERNAL:
     * Return the Descriptor with the default root mapping matching the QName
     * parameter.
     */
    public DESCRIPTOR getDescriptor(QName qName) {
        XPathQName xpathQName = new XPathQName(qName, true);
        return contextState.getDescriptor(xpathQName);
    }

    /**
     * INTERNAL:
     * Return the Descriptor with the default root mapping matching the
     * XPathQName parameter.
     */
    public DESCRIPTOR getDescriptor(XPathQName xpathQName) {
        return contextState.getDescriptor(xpathQName);
    }

    /**
     * INTERNAL:
     * Return the Descriptor mapped to the global type matching the
     * XPathFragment parameter.
     */
    public DESCRIPTOR getDescriptorByGlobalType(XPathFragment xPathFragment) {
        return contextState.getDescriptorByGlobalType(xPathFragment);
    }

    private XPathQueryResult getMappingForXPath(Object object, CoreObjectBuilder objectBuilder, StringTokenizer stringTokenizer, NAMESPACE_RESOLVER namespaceResolver) {
        XPathQueryResult queryResult = new XPathQueryResult();

        String xPath = "";
        FIELD field = createField(null);
        field.setNamespaceResolver(namespaceResolver);
        while (stringTokenizer.hasMoreElements()) {
            String nextToken = stringTokenizer.nextToken();
            field.setXPath(xPath + nextToken);
            field.initialize();
            CoreMapping mapping = objectBuilder.getMappingForField(field);
            if (null == mapping) {
                // XPath might have indexes, while the mapping's XPath may not,
                // so remove them and look again
                XPathFragment xPathFragment = new XPathFragment(nextToken);
                int fieldIndex = field.getXPathFragment().getIndexValue();
                int fragmentIndex = xPathFragment.getIndexValue();
                if (fieldIndex > 0 || fragmentIndex > 0) {
                    int index = fieldIndex - 1;
                    if (index < 0) {
                        index = fragmentIndex - 1;
                    }
                    String xPathNoIndexes = removeIndexesFromXPath(field.getXPath());
                    field.setXPath(xPathNoIndexes);
                    field.initialize();
                    mapping = objectBuilder.getMappingForField(field);
                    if (null == mapping) {
                        // Try adding /text()
                        field.setXPath(xPathNoIndexes + Constants.XPATH_SEPARATOR + Constants.TEXT);
                        field.initialize();
                        mapping = objectBuilder.getMappingForField(field);
                    }
                    if (null != mapping) {
                        if (field.getXPath().endsWith(Constants.TEXT) || !stringTokenizer.hasMoreElements()) {
                            // End of the line, we found a mapping so return it
                            queryResult.mapping = mapping;
                            queryResult.owner = object;
                            queryResult.index = index;
                            return queryResult;
                        } else {
                            // We need to keep looking -- get the mapping value,
                            // then recurse into getMappingForXPath with new root object
                            Object childObject = mapping.getAttributeValueFromObject(object);
                            if (mapping.isCollectionMapping()) {
                                Object collection = mapping.getAttributeValueFromObject(object);
                                if (null != collection  && List.class.isAssignableFrom(collection.getClass())) {
                                    List list = (List) collection;
                                    if (index >= list.size()) {
                                        // Index used in query is out of range, no matches
                                        return null;
                                    }
                                    childObject = list.get(index);
                                }
                            }
                            if (null == childObject) {
                                childObject = mapping.getReferenceDescriptor().getObjectBuilder().buildNewInstance();
                            }
                            CoreObjectBuilder childObjectBuilder = mapping.getReferenceDescriptor().getObjectBuilder();
                            return getMappingForXPath(childObject, childObjectBuilder, stringTokenizer, namespaceResolver);
                        }
                    }
                }
            } else {
                if (!stringTokenizer.hasMoreElements()) {
                    // End of the line, we found a mapping so return it
                    queryResult.mapping = mapping;
                    queryResult.owner = object;
                    return queryResult;
                } else {
                    // We need to keep looking -- get the mapping value,
                    // then recurse into getMappingForXPath with new root object
                    Object childObject = mapping.getAttributeValueFromObject(object);
                    if (mapping.isCollectionMapping()) {
                        Object collection = mapping.getAttributeValueFromObject(object);
                        if (null != collection && List.class.isAssignableFrom(collection.getClass())) {
                            List list = (List) collection;
                            if (0 >= list.size()) {
                                return null;
                            }
                            childObject = list.get(0);
                        }
                    }
                    if (null == childObject) {
                        childObject = mapping.getReferenceDescriptor().getObjectBuilder().buildNewInstance();
                    }
                    CoreObjectBuilder childObjectBuilder = mapping.getReferenceDescriptor().getObjectBuilder();
                    return getMappingForXPath(childObject, childObjectBuilder, stringTokenizer, namespaceResolver);
                }
            }
            xPath = xPath + nextToken + Constants.XPATH_SEPARATOR;
        }
        return null;
    }

    /**
     * INTERNAL:
     * Return the session corresponding to this class. Since the class
     * may be mapped by more that one of the projects used to create the
     * Context, this method will return the first match.
     */
    public ABSTRACT_SESSION getSession(Class<?> clazz) {
        return contextState.getSession(clazz);
    }

    /**
     * INTERNAL:
     */
    public SESSION getSession() {
        return contextState.getSession();
    }

    public ABSTRACT_SESSION getSession(DESCRIPTOR descriptor) {
        return contextState.getSession(descriptor);
    }

    /**
     * INTERNAL:
     * Return the session corresponding to this object. Since the
     * object may be mapped by more that one of the projects used to create the
     * Context, this method will return the first match.
     */
    public ABSTRACT_SESSION getSession(Object object) {
        return contextState.getSession(object);
    }

    /**
     * <p>Query the object model based on the corresponding document.  The following pairings are equivalent:</p>
     *
     * <i>Return the Customer's ID</i>
     * <pre> Integer id = context.getValueByXPath(customer, "@id", null, Integer.class);
     * Integer id = customer.getId();</pre>
     *
     * <i>Return the Customer's Name</i>
     * <pre> String name = context.getValueByXPath(customer, "ns:personal-info/ns:name/text()", null, String.class);
     * String name = customer.getName();</pre>
     *
     * <i>Return the Customer's Address</i>
     * <pre> Address address = context.getValueByXPath(customer, "ns:contact-info/ns:address", aNamespaceResolver, Address.class);
     * Address address = customer.getAddress();</pre>
     *
     * <i>Return all the Customer's PhoneNumbers</i>
     * <pre> List phoneNumbers = context.getValueByXPath(customer, "ns:contact-info/ns:phone-number", aNamespaceResolver, List.class);
     * List phoneNumbers = customer.getPhoneNumbers();</pre>
     *
     * <i>Return the Customer's second PhoneNumber</i>
     * <pre> PhoneNumber phoneNumber = context.getValueByXPath(customer, "ns:contact-info/ns:phone-number[2]", aNamespaceResolver, PhoneNumber.class);
     * PhoneNumber phoneNumber = customer.getPhoneNumbers().get(1);</pre>
     *
     * <i>Return the base object</i>
     * <pre> Customer customer = context.getValueByXPath(customer, ".", aNamespaceResolver, Customer.class);
     * Customer customer = customer;
     * </pre>
     *
     * @param <T> The return type of this method corresponds to the returnType parameter.
     * @param object  The XPath will be executed relative to this object.
     * @param xPath The XPath statement
     * @param namespaceResolver A NamespaceResolver containing the prefix/URI pairings from the XPath statement.
     * @param returnType The return type.
     * @return The object corresponding to the XPath or null if no result was found.
     */
    public <T> T getValueByXPath(Object object, String xPath, NAMESPACE_RESOLVER namespaceResolver, Class<T> returnType) {
        if (null == xPath || null == object) {
            return null;
        }
        if (".".equals(xPath)) {
            return (T) object;
        }
        ABSTRACT_SESSION session = this.getSession(object);
        DESCRIPTOR descriptor = (DESCRIPTOR) session.getDescriptor(object);
        StringTokenizer stringTokenizer = new StringTokenizer(xPath, Constants.XPATH_SEPARATOR);
        T value = getValueByXPath(object, descriptor.getObjectBuilder(), stringTokenizer, namespaceResolver, returnType);
        if (null == value) {
            CoreMapping selfMapping = descriptor.getObjectBuilder().getMappingForField(createField(String.valueOf(Constants.DOT)));
            if (null != selfMapping && selfMapping.getReferenceDescriptor() != null) {
                return getValueByXPath(selfMapping.getAttributeValueFromObject(object), selfMapping.getReferenceDescriptor().getObjectBuilder(),
                        new StringTokenizer(xPath, Constants.XPATH_SEPARATOR),  ((DESCRIPTOR) selfMapping.getReferenceDescriptor()).getNamespaceResolver(), returnType);
            }
        }
        return value;
    }

    private <T> T getValueByXPath(Object object, CoreObjectBuilder objectBuilder, StringTokenizer stringTokenizer, NAMESPACE_RESOLVER namespaceResolver, Class<T> returnType) {
        XPathQueryResult queryResult = getMappingForXPath(object, objectBuilder, stringTokenizer, namespaceResolver);

        if (null != queryResult) {
            CoreMapping mapping = queryResult.mapping;
            Object owner = queryResult.owner;
            Integer index = queryResult.index;

            if (null != owner) {
                Object childObject = null;
                if (mapping.isCollectionMapping()) {
                    Object collection = mapping.getAttributeValueFromObject(owner);
                    if (List.class.isAssignableFrom(collection.getClass())) {
                        List list = (List) collection;
                        if (null == index) {
                            return (T) collection;
                        }
                        if (index >= list.size()) {
                            return null;
                        }
                        childObject = list.get(index);
                    }
                } else {
                    childObject = mapping.getAttributeValueFromObject(owner);
                }
                return (T) childObject;
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Return true if any session held onto by this context has a document preservation
     * policy that requires unmarshalling from a Node.
     */
    public abstract boolean hasDocumentPreservation();

    private String removeIndexesFromXPath(String xpathWithIndexes) {
        String newXPath = xpathWithIndexes;
        while (newXPath.contains(Constants.XPATH_INDEX_OPEN)) {
            int open = newXPath.lastIndexOf(Constants.XPATH_INDEX_OPEN);
            int closed = newXPath.lastIndexOf(Constants.XPATH_INDEX_CLOSED);
            newXPath = newXPath.substring(0, open) + newXPath.substring(closed + 1);
        }
        return newXPath;
    }

    private void setValueByXPath(Object object, CoreObjectBuilder objectBuilder, StringTokenizer stringTokenizer, NAMESPACE_RESOLVER namespaceResolver, Object value) {
        XPathQueryResult queryResult = getMappingForXPath(object, objectBuilder, stringTokenizer, namespaceResolver);

        if (null != queryResult) {
            CoreMapping mapping = queryResult.mapping;
            Object owner = queryResult.owner;
            Integer index = queryResult.index;

            if (null != owner) {
                if (mapping.isCollectionMapping()) {
                    Object childObject = null;
                    Object collection = mapping.getAttributeValueFromObject(owner);
                    if (List.class.isAssignableFrom(collection.getClass())) {
                        List list = (List) collection;
                        if (null == index) {
                            // We are setting the whole collection, not an element in the collection
                            if (value.getClass().isArray()) {
                                ArrayList newList = new ArrayList();
                                int length = Array.getLength(value);
                                for (int i = 0; i < length; i++) {
                                    newList.add(Array.get(value, i));
                                }
                                value = newList;
                            }
                            mapping.setAttributeValueInObject(owner, value);
                            return;
                        }
                        if (index >= list.size()) {
                            return;
                        }
                        // Set into collection
                        list.set(index, value);
                        mapping.setAttributeValueInObject(owner, list);
                        return;
                    }
                } else {
                    mapping.setAttributeValueInObject(owner, value);
                }
            }
        }
    }

    /**
     * <p>Set values in the object model based on the corresponding document.  The following pairings are equivalent:</p>
     *
     * <i>Set the Customer's ID</i>
     * <pre> context.setValueByXPath(customer, "@id", null, Integer.valueOf(123));
     * customer.setId(Integer.valueOf(123));</pre>
     *
     * <i>Set the Customer's Name</i>
     * <pre> context.setValueByXPath(customer, "ns:personal-info/ns:name/text()", aNamespaceResolver, "Jane Doe");
     * customer.setName("Jane Doe");</pre>
     *
     * <i>Set the Customer's Address</i>
     * <pre> context.setValueByXPath(customer, "ns:contact-info/ns:address", aNamespaceResolver, anAddress);
     * customer.setAddress(anAddress);</pre>
     *
     * <i>Set the Customer's PhoneNumbers</i>
     * <pre> context.setValueByXPath(customer, "ns:contact-info/ns:phone-number", aNamespaceResolver, phoneNumbers);
     * customer.setPhoneNumbers(phoneNumbers);</pre>
     *
     * <i>Set the Customer's second PhoneNumber</i>
     * <pre> context.setValueByXPath(customer, "ns:contact-info/ns:phone-number[2]", aNamespaceResolver, aPhoneNumber);
     * customer.getPhoneNumbers().get(1);</pre>
     *
     * @param object  The XPath will be executed relative to this object.
     * @param xPath The XPath statement
     * @param namespaceResolver A NamespaceResolver containing the prefix/URI pairings from the XPath statement.
     * @param value The value to be set.
     */
    public void setValueByXPath(Object object, String xPath, NAMESPACE_RESOLVER namespaceResolver, Object value) {
        ABSTRACT_SESSION session = this.getSession(object);
        DESCRIPTOR descriptor = (DESCRIPTOR) session.getDescriptor(object);
        StringTokenizer stringTokenizer = new StringTokenizer(xPath, "/");
        setValueByXPath(object, descriptor.getObjectBuilder(), stringTokenizer, namespaceResolver, value);
    }

}
