/*
 * 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.oxm.mappings.nullpolicy;

import org.eclipse.persistence.core.sessions.CoreSession;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.NullCapableValue;
import org.eclipse.persistence.internal.oxm.XPathEngine;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.XPathNode;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.record.AbstractMarshalRecord;
import org.eclipse.persistence.internal.oxm.record.MarshalRecord;
import org.eclipse.persistence.internal.oxm.record.XMLRecord;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;

/**
 * PUBLIC: <b>Description</b>: This node null policy allows for the handling of
 * various representations of null in XML documents.<br>
 * <p>
 * <b>Null policies have 2 concrete implementations</b>:
 * <ul>
 * <li> NullPolicy (default implementation)</li>
 * <li> IsSetNullPolicy (keyed off isSet() state of the node)</li>
 * </ul>
 *
 * <table border="1">
 * <caption>Unmarshalling</caption>
 * <tr>
 * <th id="c1">Unmarshal Flag</th>
 * <th id="c2">Description</th>
 * </tr>
 * <tr>
 * <td headers="c1"> isSetPerformedForAbsentNode </td>
 * <td headers="c2">This umarshal flag represents whether a set is done for
 * absent nodes only.</td>
 * </tr>
 * <tr>
 * <td headers="c1"> isNullRepresentedByEmptyNode </td>
 * <td headers="c2">If this unmarshal flag is false for empty nodes we set an
 * empty Object for composite mappings, otherwise we set to null.</td>
 * </tr>
 * <tr>
 * <td headers="c1" style="nowrap"> isNullRepresentedByXsiNil </td>
 * <td headers="c2">If this unmarshal flag is false for xsi:nil nodes we ignore
 * the xsi:nil attribute and treat as an empty node.<br>
 * Otherwise we set to null.</td>
 * </tr>
 * </table>
 *
 * <table border="1">
 * <caption>Marshalling</caption>
 * <tr>
 * <th id="c3">Marshal Enum</th>
 * <th id="c4">XMLNullRepresentationType Description</th>
 * </tr>
 * <tr>
 * <td headers="c3"> XSI_NIL </td>
 * <td headers="c4">Nillable: Write out an xsi:nil="true" attribute.</td>
 * </tr>
 * <tr>
 * <td headers="c3"> ABSENT_NODE(default) </td>
 * <td headers="c4">Optional: Write out no node.</td>
 * </tr>
 * <tr>
 * <td headers="c3" style="nowrap"> EMPTY_NODE </td>
 * <td headers="c4">Required: Write out an empty {@literal <node/>} or node="" node.</td>
 * </tr>
 * </table> &nbsp;<b>Usage</b>:<br>
 *
 * @see org.eclipse.persistence.internal.oxm.NullCapableValue
 * @since Oracle TopLink 11<i>g</i> Release 1 (11.1.1)
 */
public abstract class AbstractNullPolicy {
    protected static final String TRUE = "true";
    protected static final String COLON_W_SCHEMA_NIL_ATTRIBUTE = Constants.COLON + Constants.SCHEMA_NIL_ATTRIBUTE;
    protected static final String XSI_NIL_ATTRIBUTE = Constants.SCHEMA_INSTANCE_PREFIX + COLON_W_SCHEMA_NIL_ATTRIBUTE;

    /**
     * This state flag determines how we unmarshal absent nodes. true =
     * (default) Perform a set(null). false = Do not perform a set(null).
     */
    protected boolean isSetPerformedForAbsentNode = true;

    /**
     * This state flag determines how we unmarshal empty nodes. true = Perform a
     * set(null) or primitive type equivalent. false = (default) Perform a
     * set(new Object()).
     */
    protected boolean isNullRepresentedByEmptyNode = false;

    /**
     * This state flag determines how we unmarshal xsi:nil nodes. A set is
     * performed in both cases. true = Perform a set(null) or primitive type
     * equivalent.. false = (default) do nothing and treat as an empty node.
     */
    protected boolean isNullRepresentedByXsiNil = false;

    /**
     * This state flag determines how we unmarshal xsi:nil nodes when there
     * are other attributes (other than xsi:nil) present. If false, we ignore
     * any attributes and treat the element as nil. If true, we inspect if
     * some attributes are present and if yes, we process them.
     */
    protected boolean ignoreAttributesForNil = true;

    /**
     * This enum instance determines what to write out during a marshal
     * operation. We are defaulting to ABSENT_NODE
     */
    protected XMLNullRepresentationType marshalNullRepresentation = XMLNullRepresentationType.ABSENT_NODE;

    /**
     * Default constructor.
     */
    protected AbstractNullPolicy() {
    }

    /**
     * Get the enum that determines what XML to write when a null value is encountered.
     */
    public XMLNullRepresentationType getMarshalNullRepresentation() {
        return marshalNullRepresentation;
    }

    /**
     * Set the enum that determines what XML to write when a null value is encountered.
     */
    public void setMarshalNullRepresentation(XMLNullRepresentationType anEnumInstance) {
        marshalNullRepresentation = anEnumInstance;
    }

    /**
     * INTERNAL:
     * When using the SAX or DOM Platform, this method is responsible for
     * marshalling null values for the XML Direct Mapping.
     *
     * @param xPathFragment
     * @param marshalRecord
     * @param object
     * @param session
     * @param namespaceResolver
     * @return true if this method caused any nodes to be marshaled, else false.
     */
    public boolean directMarshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, //
                    Object object, CoreSession session, NamespaceResolver namespaceResolver) {
        // Handle attributes - XSI_NIL, ABSENT_NODE have the same behavior
        if (xPathFragment.isAttribute()) {
            // Write out an empty attribute
            if (marshalNullRepresentation == XMLNullRepresentationType.EMPTY_NODE) {
                marshalRecord.emptyAttribute(xPathFragment, namespaceResolver);
                return true;
            } else {
                // XSI_NIL attributes are invalid - and are ignored
                // ABSENT_NODE - Write out nothing
                return false;
            }
        } else {
            // Nillable: write out xsi:nil="true" attribute in empty element
            if (marshalNullRepresentation == XMLNullRepresentationType.XSI_NIL) {
                marshalRecord.nilSimple(namespaceResolver);
                return true;
            } else {
                // EMPTY_NODE - Write out empty element
                if (marshalNullRepresentation == XMLNullRepresentationType.EMPTY_NODE) {
                    marshalRecord.emptySimple(namespaceResolver);
                    return true;
                } else {
                    // ABSENT_NODE - Write out nothing
                    return false;
                }
            }
        }
    }

    /**
     * INTERNAL: When using the SAX Platform, this method is responsible for
     * marshalling null values for the XML Composite Object Mapping.
     *
     * @param xPathFragment
     * @param marshalRecord
     * @param object
     * @param session
     * @param namespaceResolver
     * @return true if this method caused any nodes to be marshaled, else false.
     */
    public boolean compositeObjectMarshal(XPathFragment xPathFragment, MarshalRecord marshalRecord, //
              Object object, CoreSession session, NamespaceResolver namespaceResolver) {
        if (marshalNullRepresentation == XMLNullRepresentationType.ABSENT_NODE){
            return false;
        }
        // Nillable
        else if (marshalNullRepresentation == XMLNullRepresentationType.XSI_NIL) {
            marshalRecord.nilComplex(xPathFragment, namespaceResolver);
            return true;
        } else if (marshalNullRepresentation == XMLNullRepresentationType.EMPTY_NODE) {
            // Optional and Required
            // This call is really only valid when using DOM - TBD false
            // Write out empty element - we need to differentiate between
            // object=null and object=new Object() with null fields and 0-numeric primitive values
            // EMPTY_NODE - Write out empty element - Required
                marshalRecord.emptyComplex(xPathFragment, namespaceResolver);
                return true;
        }
        return false;
    }

    /**
     * INTERNAL: When using the DOM Platform, this method is responsible for
     * marshalling null values for the XML Composite Object Mapping.
     *
     * @param record
     * @param object
     * @param field
     * @return true if this method caused any objects to be marshaled, else false.
     */
    public boolean compositeObjectMarshal(AbstractMarshalRecord record, Object object, Field field, CoreAbstractSession session) {
        if (marshalNullRepresentation == XMLNullRepresentationType.XSI_NIL) {
            record.put(field, XMLRecord.NIL);
            return true;
        } else {
            // EMPTY_NODE - Write out empty element - Required
            if (marshalNullRepresentation == XMLNullRepresentationType.EMPTY_NODE) {
                Node element = XPathEngine.getInstance().createUnownedElement(record.getDOM(), field);
                record.put(field, element);
                return true;
            } else {
                // ABSENT_NODE - Write out nothing - Optional
                return false;
            }
        }
    }

    /**
     * INTERNAL: When using the SAX or DOM Platform during unmarshal operations.
     * Use the attributes to determine if the element represents a null value.
     *
     * @param attributes
     * @return true if based on the attributes the corresponding element
     *         represents a null value, else false.
     */
    public boolean valueIsNull(Attributes attributes) {
        // Nillable
        if (isNullRepresentedByXsiNil()) {
            // Ignore any other attributes that are in addition to xsi:nil
            if(null == attributes) {
                return false;
            }
            return attributes.getValue(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_NIL_ATTRIBUTE) != null;
        } else {
            // EMPTY_NODE - Required
            if (isNullRepresentedByEmptyNode() && (null == attributes || attributes.getLength() == 0)) {
                return true;
            }
        }
        return false;
    }


    /**
     * INTERNAL: When using the DOM Platform during unmarshal operations.
     * Use the element to determine if the element represents a null value.
     *
     * @param element
     * @return true if based on the element it represents a null value, else false.
     */
    public boolean valueIsNull(Element element) {
        // Check Nillable: Ignore any other attributes that are in addition to xsi:nil
        if (null == element) {
            return true;
        } else {
            if (isNullRepresentedByXsiNil() && element.hasAttributeNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_NIL_ATTRIBUTE)) {
                return true;
            } else {
                // EMPTY_NODE - Required
                // Verify no attributes and no child nodes on the DOM element
                if (isNullRepresentedByEmptyNode() && !element.hasAttributes() && (element.getChildNodes().getLength() == 0)) {
                    return true;
                } else {
                    return false;
                }
            }
        }
    }

    /**
     * INTERNAL: When using the SAX Platform this allows a NodeValue to be
     * registered to receive events from the TreeObjectBuilder.
     * @param xPathNode
     * @param nullCapableValue
     */
    public abstract void xPathNode(XPathNode xPathNode, NullCapableValue nullCapableValue);

    /**
     * @return the isSetPerformedForAbsentNode flag
     */
    public boolean getIsSetPerformedForAbsentNode() {
        return isSetPerformedForAbsentNode;
    }

    /**
     *
     * @return
     */
    public boolean isNullRepresentedByEmptyNode() {
        return isNullRepresentedByEmptyNode;
    }

    /**
     *
     * @param bIsNullRepresentedByEmptyNode
     */
    public void setNullRepresentedByEmptyNode(boolean bIsNullRepresentedByEmptyNode) {
        isNullRepresentedByEmptyNode = bIsNullRepresentedByEmptyNode;
    }

    /**
     *
     * @return
     */
    public boolean isNullRepresentedByXsiNil() {
        return isNullRepresentedByXsiNil;
    }

    /**
     *
     * @param bIsNullRepresentedByXsiNil
     */
    public void setNullRepresentedByXsiNil(boolean bIsNullRepresentedByXsiNil) {
        isNullRepresentedByXsiNil = bIsNullRepresentedByXsiNil;
    }

    /**
     *
     * @return
     */
    public boolean ignoreAttributesForNil() {
        return ignoreAttributesForNil;
    }

    /**
     *
     * @param ignoreAttributesForNil
     */
    public void setIgnoreAttributesForNil(boolean ignoreAttributesForNil) {
        this.ignoreAttributesForNil = ignoreAttributesForNil;
    }

    /**
     * INTERNAL:
     * Private function to process or create an entry in the NamespaceResolver for the xsi prefix.
     * @param namespaceResolver
     * @return xsi prefix
     */
    protected String processNamespaceResolverForXSIPrefix(NamespaceResolver namespaceResolver, MarshalRecord marshalRecord) {
        String xsiPrefix;
        if (null == namespaceResolver) {
            // add new xsi entry into the properties map
            xsiPrefix = Constants.SCHEMA_INSTANCE_PREFIX;
              marshalRecord.namespaceDeclaration(xsiPrefix, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
        } else {
            // find an existing xsi entry in the map
            xsiPrefix = namespaceResolver.resolveNamespaceURI(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
            if (null == xsiPrefix) {
                xsiPrefix = namespaceResolver.generatePrefix(Constants.SCHEMA_INSTANCE_PREFIX);
                marshalRecord.namespaceDeclaration(xsiPrefix, javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
            }
        }
        return xsiPrefix;
    }

    /**
     * INTERNAL
     */
    public void directMarshal(Field field, AbstractMarshalRecord record, Object object) {
        Object fieldValue = null;
        if(marshalNullRepresentation == XMLNullRepresentationType.EMPTY_NODE) {
            fieldValue = Constants.EMPTY_STRING;
        } else {
            if(!field.getLastXPathFragment().isAttribute()) {
                if(marshalNullRepresentation == XMLNullRepresentationType.XSI_NIL) {
                    fieldValue = XMLRecord.NIL;
                }
            }
        }
        record.put(field, fieldValue);
    }
}
