Package org.eclipse.persistence.internal.oxm

Source Code of org.eclipse.persistence.internal.oxm.XPathNode

/*******************************************************************************
* Copyright (c) 1998, 2011 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
*     Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/ 
package org.eclipse.persistence.internal.oxm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.record.MarshalContext;
import org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.record.MarshalRecord;

/**
* INTERNAL:
* <p><b>Purpose</b>:  XPathNodes are used together to build a tree.  The tree
* is built from all of the XPath statements specified in the mapping metadata
* (mappings and policies).  This tree is then navigated by the
* TreeObjectBuilder to perform marshal and unmarshal operations.</p>
* <p>The XPaths "a/b" and "a/c" would result in a tree with the root "a" and
* two child nodes "b" and "c".</p>
* <p><b>Responsibilities</b>:<ul>
* <li>All tree relationships must be bi-directional.</li>
* <li>Reference a NodeValue, XPathNodes without a Node value represent grouping
* elements.</li>
* <li>Reference an XPathFragment, XPathFragments contain name and namespace
* information.</li>
* <li>Must differentiate between child nodes that correspond to elements and
* those that do not.</li>
* <li>Must represent special mapping situations like any and self mappings.</li>
* </ul>
*/

public class XPathNode {
    private NodeValue unmarshalNodeValue;
    private NodeValue marshalNodeValue;
    private XPathFragment xPathFragment;
    private XPathNode parent;
    private List<XPathNode> attributeChildren;
    private List<XPathNode> nonAttributeChildren;
    private List<XPathNode> selfChildren;
    private Map<XPathFragment, XPathNode> attributeChildrenMap;
    private Map<XPathFragment, XPathNode> nonAttributeChildrenMap;
    private XMLAnyAttributeMappingNodeValue anyAttributeNodeValue;
    private XPathNode anyAttributeNode;
    private XPathNode textNode;
    private XPathNode anyNode;

    public XPathFragment getXPathFragment() {
        return xPathFragment;
    }

    public void setXPathFragment(XPathFragment xPathFragment) {
        this.xPathFragment = xPathFragment;
    }

    public NodeValue getNodeValue() {
        return unmarshalNodeValue;
    }

    public void setNodeValue(NodeValue nodeValue) {
        this.marshalNodeValue = nodeValue;
        this.unmarshalNodeValue = nodeValue;
        if (null != nodeValue) {
            nodeValue.setXPathNode(this);
        }
    }
   
    public NodeValue getUnmarshalNodeValue() {
        return unmarshalNodeValue;
    }
   
    public void setUnmarshalNodeValue(NodeValue nodeValue) {
        if (null != nodeValue) {
            nodeValue.setXPathNode(this);
        }
        this.unmarshalNodeValue = nodeValue;
    }

    public NodeValue getMarshalNodeValue() {
        return marshalNodeValue;
    }
   
    public void setMarshalNodeValue(NodeValue nodeValue) {
        if (null != nodeValue) {
            nodeValue.setXPathNode(this);
        }
        this.marshalNodeValue = nodeValue;
    }
   
    public XPathNode getParent() {
        return parent;
    }

    public void setParent(XPathNode parent) {
        this.parent = parent;
    }

    public List<XPathNode> getAttributeChildren() {
        return this.attributeChildren;
    }

    public List<XPathNode> getNonAttributeChildren() {
        return this.nonAttributeChildren;
    }

    public List<XPathNode> getSelfChildren() {
        return this.selfChildren;
    }

    public Map<XPathFragment, XPathNode> getNonAttributeChildrenMap() {
        return this.nonAttributeChildrenMap;
    }

    public Map<XPathFragment, XPathNode> getAttributeChildrenMap() {
        return this.attributeChildrenMap;
    }

    public void setAnyAttributeNodeValue(XMLAnyAttributeMappingNodeValue nodeValue) {
        this.anyAttributeNodeValue = nodeValue;
    }

    public XMLAnyAttributeMappingNodeValue getAnyAttributeNodeValue() {
        return this.anyAttributeNodeValue;
    }

    public XPathNode getAnyAttributeNode() {
        return this.anyAttributeNode;
    }

    public XPathNode getAnyNode() {
        return this.anyNode;
    }

    public void setAnyNode(XPathNode xPathNode) {
        this.anyNode = xPathNode;
    }

    public XPathNode getTextNode() {
        return this.textNode;
    }

    public void setTextNode(XPathNode xPathNode) {
        this.textNode = xPathNode;
    }

    public boolean equals(Object object) {
        try {
            XPathFragment perfNodeXPathFragment = ((XPathNode)object).getXPathFragment();
            if(xPathFragment == perfNodeXPathFragment) {
                return true;
            } else if(null == xPathFragment) {
                return false;
            } else if(null == perfNodeXPathFragment) {
                return false;
            }
            return xPathFragment.equals(perfNodeXPathFragment);

            // turn fix off for now until we re-enable XMLAnyObjectAndAnyCollectionTestCases
            //          } catch (NullPointerException npe) {
            // b5259059 all cases X0X1 (1mapping xpath=null, 2nd mapping xpath=filled
            // catch when object.getXPathFragment() == null
            // (this will also catch case where perfNode XPath is null)
            //            return false;
        } catch (ClassCastException e) {
            return false;
        }
    }

    public XPathNode addChild(XPathFragment anXPathFragment, NodeValue aNodeValue, NamespaceResolver namespaceResolver) {
        if (null != anXPathFragment && anXPathFragment.nameIsText()) {
            if (aNodeValue.isOwningNode(anXPathFragment)) {
                XPathNode textXPathNode = new XPathNode();
                textXPathNode.setParent(this);
                textXPathNode.setXPathFragment(anXPathFragment);
                if (aNodeValue.isMarshalNodeValue()) {
                    textXPathNode.setMarshalNodeValue(aNodeValue);
                }
                if (aNodeValue.isUnmarshalNodeValue()) {
                    textXPathNode.setUnmarshalNodeValue(aNodeValue);
                }
                this.setTextNode(textXPathNode);
                if (null == nonAttributeChildren) {
                    nonAttributeChildren = new ArrayList();
                }
                nonAttributeChildren.add(textXPathNode);
                return textXPathNode;
            }
        }

        if (anXPathFragment != null && namespaceResolver != null && anXPathFragment.getNamespaceURI() == null && !anXPathFragment.nameIsText()) {
            if(!anXPathFragment.isAttribute()) {
                anXPathFragment.setNamespaceURI(namespaceResolver.resolveNamespacePrefix(anXPathFragment.getPrefix()));
            } else if(anXPathFragment.hasNamespace()) {
                anXPathFragment.setNamespaceURI(namespaceResolver.resolveNamespacePrefix(anXPathFragment.getPrefix()));
            }
        }

        XPathNode xPathNode = new XPathNode();
        xPathNode.setXPathFragment(anXPathFragment);

        List children;
        Map childrenMap;

        if ((anXPathFragment != null) && anXPathFragment.isAttribute()) {
            if (null == attributeChildren) {
                attributeChildren = new ArrayList();
            }
            if (null == attributeChildrenMap) {
                attributeChildrenMap = new HashMap();
            }
            children = attributeChildren;
            childrenMap = attributeChildrenMap;
        } else {
            if (null == nonAttributeChildren) {
                nonAttributeChildren = new ArrayList();
            }
            if (null == nonAttributeChildrenMap) {
                nonAttributeChildrenMap = new HashMap();
            }
            children = nonAttributeChildren;
            childrenMap = nonAttributeChildrenMap;
        }

        if (null == anXPathFragment) {
            if(aNodeValue.isMarshalNodeValue()) {
                xPathNode.setMarshalNodeValue(aNodeValue);
            }
            if(aNodeValue.isUnmarshalNodeValue() && xPathNode.getUnmarshalNodeValue() == null) {
                xPathNode.setUnmarshalNodeValue(aNodeValue);
            }
            xPathNode.setParent(this);
            if (aNodeValue instanceof XMLAnyAttributeMappingNodeValue) {
                setAnyAttributeNodeValue((XMLAnyAttributeMappingNodeValue)aNodeValue);
                anyAttributeNode = xPathNode;
            } else {
                if(!children.contains(xPathNode)) {
                    children.add(xPathNode);
                }
                setAnyNode(xPathNode);
            }
            return xPathNode;
        }
        boolean isSelfFragment = XPathFragment.SELF_FRAGMENT.equals(anXPathFragment);

        if(isSelfFragment){
            children.add(xPathNode);
            if (null == selfChildren) {
                selfChildren = new ArrayList<XPathNode>();
            }
            selfChildren.add(xPathNode);
        }else{
            int index = children.indexOf(xPathNode);
            if (index >= 0) {
                xPathNode = (XPathNode)children.get(index);
            } else {
                xPathNode.setParent(this);
                if(!children.contains(xPathNode)) {
                    children.add(xPathNode);
                }
                childrenMap.put(anXPathFragment, xPathNode);
            }
        }

        if (aNodeValue.isOwningNode(anXPathFragment)) {
            if(aNodeValue.isMarshalNodeValue()) {
                xPathNode.setMarshalNodeValue(aNodeValue);
            }
            if(aNodeValue.isUnmarshalNodeValue() && xPathNode.getUnmarshalNodeValue() == null) {
                xPathNode.setUnmarshalNodeValue(aNodeValue);
            }
        } else {
            XPathFragment nextFragment = anXPathFragment.getNextFragment();
            xPathNode.addChild(nextFragment, aNodeValue, namespaceResolver);
        }
        return xPathNode;
    }

    public boolean marshal(MarshalRecord marshalRecord, Object object, AbstractSession session, NamespaceResolver namespaceResolver, XMLMarshaller marshaller, MarshalContext marshalContext, XPathFragment rootFragment) {
        if ((null == marshalNodeValue) || marshalNodeValue.isMarshalOnlyNodeValue()) {
            marshalRecord.addGroupingElement(this);

            boolean hasValue = false;
            if (null != attributeChildren) {
                for (int x = 0, size = attributeChildren.size(); x < size; x++) {
                    XPathNode xPathNode = attributeChildren.get(x);
                    hasValue = xPathNode.marshal(marshalRecord, object, session, namespaceResolver, marshaller, ObjectMarshalContext.getInstance(), this.xPathFragment) || hasValue;
                }
            }
            if (anyAttributeNode != null) {
                hasValue = anyAttributeNode.marshal(marshalRecord, object, session, namespaceResolver, marshaller, ObjectMarshalContext.getInstance(), null) || hasValue;
            }
            if (null != nonAttributeChildren) {
                for (int x = 0, size = marshalContext.getNonAttributeChildrenSize(this); x < size; x++) {
                    XPathNode xPathNode = (XPathNode)marshalContext.getNonAttributeChild(x, this);
                    MarshalContext childMarshalContext = marshalContext.getMarshalContext(x);
                    hasValue = xPathNode.marshal(marshalRecord, object, session, namespaceResolver, marshaller, childMarshalContext, this.xPathFragment) || hasValue;
                }
            }

            if (hasValue) {
                marshalRecord.endElement(xPathFragment, namespaceResolver);
            } else {
                marshalRecord.removeGroupingElement(this);
            }

            return hasValue;
        } else {
            return marshalContext.marshal(marshalNodeValue, xPathFragment, marshalRecord, object, session, namespaceResolver, rootFragment);
        }
    }

    public boolean startElement(MarshalRecord marshalRecord, XPathFragment anXPathFragment, Object object, AbstractSession session, NamespaceResolver namespaceResolver, TreeObjectBuilder compositeObjectBuilder, Object compositeObject) {
        if (null == anXPathFragment) {
            return false;
        }
        marshalRecord.openStartElement(anXPathFragment, namespaceResolver);
        boolean hasValue = false;

        marshalRecord.predicateAttribute(anXPathFragment, namespaceResolver);

        if (null != attributeChildren) {
            for (int x = 0, size = attributeChildren.size(); x < size; x++) {
                XPathNode attributeNode = attributeChildren.get(x);
                hasValue = attributeNode.marshal(marshalRecord, object, session, namespaceResolver, null, ObjectMarshalContext.getInstance(), null) || hasValue;
            }
        }
        if (anyAttributeNode != null) {
            //marshal the anyAttribute node here before closeStartElement()
            hasValue = anyAttributeNode.marshal(marshalRecord, object, session, namespaceResolver, null, ObjectMarshalContext.getInstance(), null) || hasValue;
        }

        if (null != compositeObjectBuilder) {
            hasValue = compositeObjectBuilder.marshalAttributes(marshalRecord, compositeObject, session) || hasValue;
        }
        marshalRecord.closeStartElement();
        return hasValue;
    }

    /**
     * Marshal any 'self' mapped attributes. 
     *
     * @param marshalRecord
     * @param object
     * @param session
     * @param namespaceResolver
     * @param marshaller
     * @return
     */
    public boolean marshalSelfAttributes(MarshalRecord marshalRecord, Object object, AbstractSession session, NamespaceResolver namespaceResolver, XMLMarshaller marshaller) {
        if (marshalNodeValue == null) {
            return false;
        }
        return marshalNodeValue.marshalSelfAttributes(xPathFragment, marshalRecord, object, session, namespaceResolver, marshaller);
    }

    public boolean isWhitespaceAware() {
        return unmarshalNodeValue.isWhitespaceAware();
    }

}
TOP

Related Classes of org.eclipse.persistence.internal.oxm.XPathNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.