Package com.ibm.commons.xml.xpath

Source Code of com.ibm.commons.xml.xpath.AbstractSimpleExpression

/*
* © Copyright IBM Corp. 2012
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

/*
* Created on May 29, 2005
*
*/
package com.ibm.commons.xml.xpath;

import java.util.ArrayList;
import java.util.Iterator;

import com.ibm.commons.util.StringUtil;
import com.ibm.commons.xml.NamespaceContext;
import com.ibm.commons.xml.XResult;
import com.ibm.commons.xml.xpath.part.Part;
import com.ibm.commons.xml.xpath.xml.Utils;

/**
* @author Mark Wallace
* @author Eugene Konstantinov
* @author Philippe Riand
*/
abstract public class AbstractSimpleExpression extends AbstractExpression {

    protected boolean _isFromRoot;

    protected Part[] _parts;
   
    /**
     * Construct a SimpleXPathExpression with the specified properties
     *
     * @param expression
     * @param fromRoot
     * @param parts
     */
    public AbstractSimpleExpression(String expression, boolean isFromRoot,
            Part[] parts) {
        super(expression);

        _isFromRoot = isFromRoot;
        _parts = parts;
    }

    /**
     * Return true if this expression is relative to the root, otherwise return
     * false.
     *
     * @return true if this expression is relative to the root
     */
    public boolean isFromRoot() {
        return _isFromRoot;
    }

    /**
     * Return the count of Part objects associated with this
     * SimpleXPathExpression.
     *
     * @return the count of Part objects
     */
    public int getPartCount() {
        return (_parts != null) ? _parts.length : 0;
    }

    /**
     * Return the nth Part object associated with this SimpleXPathExpression.
     *
     * @param index
     * @return the nth Part object
     */
    public Part getPart(int index) {
        return (_parts != null) ? _parts[index] : null;
    }

    //
    // Implementation of XPathExpression
    //

    /**
     *
     * @see com.ibm.xfaces.xpath.XPathExpression#isSimple()
     */
    public boolean isSimple() {
        return true;
    }

    /**
     * Evaluates this simple xpath expression.
     * <p>
     * The algorithm for evaluation iteratively step through each part of the
     * xpath calling evaluatePart()
     *
     * @param node
     *            the node evaluation start from
     * @see com.ibm.xfaces.xpath.XPathExpression#isSimple()
     * @see #evaluatePart(Object, Part)
     */
    protected XResult doEval(Object node, NamespaceContext namespaceContext) throws XPathException {
        try {
            if(isFromRoot()) {
                node = getRootNode(node);
            }
           
            namespaceContext = resolveNamespaceContext(node,namespaceContext);
           
            int count = (_parts != null) ? _parts.length : 0;

            if (count== 0 && StringUtil.isEmpty(getExpression())) {
                throw new XPathException(null,
                        "Incorrect XPATH: Empty text was provided"); // $NLS-AbstractSimpleExpression.IncorrectXPATHEmptytextwasprovide-1$
            }

            for(int pos = 0; pos < count && node != null; pos++) {
                node = evaluatePart(node, _parts[pos], namespaceContext);
            }
            return wrapUp(node);
        } catch (Exception e) {
//            System.err.println("Evaluation error for: " + getExpression()
//                    + " Root cause:" + e.getMessage());
            throw new XPathException(e);
        }
    }

    /**
     * Sets up the new value of the node
     *
     * @param node
     *            the node the new value is being set
     * @param value
     *            the new value for the node
     * @param autoCreate
     *            set to <code>true</code> to indicate that node must be
     *            created if it doesnot exist
     * @see com.ibm.xfaces.xpath.XPathExpression#setValue(Object, Object,
     *      boolean)
     */
    protected void doSetValue(Object node, Object value, NamespaceContext namespaceContext, boolean autoCreate) throws XPathException {
        if(isFromRoot()) {
            node = getRootNode(node);
        }
        Object curObject = node;
        Object prevObject = null;
        try {
            if (!(isValid(node))) {
                throw new XPathException(null,"Incorrect node type for evaluation:" // $NLS-AbstractSimpleExpression.Incorrectnodetypeforevaluation-1$
                        + node.getClass());
            }
            if (getPartCount() == 0 && StringUtil.isEmpty(getExpression())) {
                throw new XPathException(null,
                        "Incorrect XPATH: Empty text was provided"); // $NLS-AbstractSimpleExpression.IncorrectXPATHEmptytextwasprovide.1-1$
            }
            namespaceContext = resolveNamespaceContext(node,namespaceContext);
           
            // evaluate all parts and create any that are missing if
            // auto create has been set to true
            Part currentPart = null;
            int currentPos = 0;
            while (getPartCount() > currentPos) {
                currentPart = getPart(currentPos);
                currentPos++;
                prevObject = curObject;
                curObject = evaluatePart(curObject, currentPart, namespaceContext);

                if (curObject == null) {
                    if (autoCreate) {
                        curObject = createPart(prevObject, currentPart, namespaceContext);
                    }
                    else {
                        throw new XPathException(null,"Evaluation error for " // $NLS-AbstractSimpleExpression.Evaluationerrorfor.1-1$
                                + currentPart.toString() + " of the XPATH:" // $NLS-AbstractSimpleExpression.oftheXPATH-1$
                                + getExpression());
                    }
                }
                if (!isValid(curObject)) {
                    throw new XPathException(null,
                            "Incorrect node type for evaluation:" // $NLS-AbstractSimpleExpression.Incorrectnodetypeforevaluation.1-1$
                                    + node.getClass());
                }
            }

            String strValue = Utils.getAsString(value);
            setNodeValue(curObject, strValue);
        }
        catch (Exception e) {
//            System.err.println("Evaluation error for : " + getExpression()
//                    + " Root cause:" + e.getMessage());
            throw new XPathException(e);
        }
    }

    /**
     * Creates node or nodes
     *
     * @param node
     *            the node the evaluation starts from
     * @return the inner most node created (corresponds to the very last part of
     *         xpath expression) or null
     * @see com.ibm.xfaces.xpath.XPathExpression#doCreateNodes(Object, Object)
     */
    protected  Object doCreateNodes(Object node, NamespaceContext namespaceContext)
            throws XPathException {
        if(isFromRoot()) {
            node = getRootNode(node);
        }

        ArrayList<Object> created = new ArrayList<Object>();
        Object curObject = node;
        try {
            if (!(isValid(node))) {
                throw new XPathException(null,"Incorrect node type for evaluation:" // $NLS-AbstractSimpleExpression.Incorrectnodetypeforevaluation.2-1$
                        + node.getClass());
            }
            if (getPartCount() == 0 && StringUtil.isEmpty(getExpression())) {
                throw new XPathException(null,
                        "Incorrect XPATH: Empty text was provided"); // $NLS-AbstractSimpleExpression.IncorrectXPATHEmptytextwasprovide.2-1$
            }
            namespaceContext = resolveNamespaceContext(node,namespaceContext);
           
            Part currentPart = null;
            int currentPos = 0;
            while (getPartCount() > currentPos) {
                currentPart = getPart(currentPos);
                currentPos++;
                Object evalObject = evaluatePart(curObject, currentPart, namespaceContext);
                if (evalObject == null) {
                    evalObject = createPart(curObject, currentPart, namespaceContext);
                    // keep record created nodes
                    if (evalObject != null) {
                        created.add(evalObject);
                    }
                }
                curObject = evalObject;
                continue;
            }
            return curObject;
        } catch (Exception e) {
            // release any created DataObjects in an event of an error
            for (Iterator<Object> iter = created.iterator(); iter.hasNext();) {
                deletePart(iter.next(), null);
            }
            throw new XPathException(e);
        }
    }

   
    /**
     * Get the root element for a particular node.
     * This method is called by absolute XPath evaluation. At leat, this method should
     * return the node itself if a root node doesn't make sense.
     * @param node
     * @return
     */
    public abstract Object getRootNode(Object node);
   
    /**
     * Creates node for the respective xpath part
     *
     * @param node
     *            the node that is parent for the newly created node
     * @param part
     *            the part of the xpath that the current node is being created
     * @return the newly create node or <code>null</code>
     */
    abstract protected Object createPart(Object node, Part part, NamespaceContext namespaceContext) throws XPathException;

    /**
     * Sets a new value to a node
     *
     * @param node
     *            the node whisch value is being set
     * @param part
     *            the part that corresponds to the node which value is being set
     * @param value
     *            the new value for the node
     */
    abstract protected void setNodeValue(Object node, Object value) throws XPathException;

    /**
     * Deletes node
     *
     * @param node
     *            the node that is being deleted
     * @param part
     *            the part that corresponds to the node
     */
    abstract protected void deletePart(Object node, Part part);

    /**
     * Evaluates the part of xpath expression
     *
     * @param node
     *            the parent node
     * @param part
     *            the part of the xpath to be evaluated
     * @return the node that corresponds with the part of the xpath
     * @throws XPathException
     */
    abstract protected Object evaluatePart(Object node, Part part, NamespaceContext namespaceContext)
            throws XPathException;

    /**
     * Returns wrapper over the node to extract value of the given node.
     * <p>
     * This wrapper object must override <code>toString()</code>to return
     * <code>String</code> representation of the node's value
     *
     * @param node
     *            the context node which value we trying to resolve
     * @return the object that wrapps up the node
     */
    abstract public XResult wrapUp(Object node) throws XPathException;

}
TOP

Related Classes of com.ibm.commons.xml.xpath.AbstractSimpleExpression

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.