All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ximpleware.AutoPilot Maven / Gradle / Ivy

/* 
 * Copyright (C) 2002-2012 XimpleWare, [email protected]
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
package com.ximpleware;


import com.ximpleware.xpath.*;
import java.util.*;
import java.io.*;
/**
 * XimpleWare's AutoPilot implementation encapsulating node iterator
 * and XPath.
 * 
 */
public class AutoPilot {
    protected int depth;
    // the depth of the element at the starting point will determine when to stop iteration
    protected int iter_type; // see selectElement
    protected VTDNav vn; // the navigator object
    protected int index; // for iterAttr
    protected int endIndex;
    protected boolean ft; // a helper variable for 
    protected boolean special;   // This helps distinguish between
    				   		   // the case of node() and * for preceding axis
    						   // of xpath evaluation
    protected String name; // Store element name after selectElement
    protected String name2; // store xmlns:+name
    protected String localName; // Store local name after selectElemntNS
    protected String URL; // Store URL name after selectElementNS
    protected int size; // for iterateAttr
    
    protected Expr xpe;	// for evalXPath
    
    protected int[] contextCopy;  //for preceding axis
    protected int stackSize;  // the stack size for xpath evaluation
    private FastIntBuffer fib; // for namespace axis
    
    protected Hashtable nsHash;
    protected boolean enableCaching;
    //private parser p;
    // defines the type of "iteration"
    public final static int UNDEFINED = 0;
    // set the mode corresponding to DOM's getElemetnbyName(string)
    public final static int SIMPLE = 1;
    // set the mode corresponding to DOM's getElementbyNameNS(string)
    public final static int SIMPLE_NS = 2;
    public final static int DESCENDANT = 3;
    public final static int DESCENDANT_NS = 4;
    public final static int FOLLOWING = 5;
    public final static int FOLLOWING_NS=6;
    public final static int PRECEDING = 7;
    public final static int PRECEDING_NS=8;
    public final static int ATTR = 9;
    public final static int ATTR_NS = 10;
    public final static int NAME_SPACE = 11;
    public final static int SIMPLE_NODE = 12;
    public final static int DESCENDANT_NODE = 13;
    public final static int FOLLOWING_NODE = 14;
    public final static int PRECEDING_NODE = 15;
    
    static private Hashtable symbolHash;
    //static int count=0;
    
 protected String getName(){
   	return name;
 }
/**
 * AutoPilot constructor comment.
 * @exception IllegalArgumentException If the VTDNav object is null 
 */
public AutoPilot(VTDNav v) {
    if (v == null)
        throw new IllegalArgumentException(" instance of VTDNav can't be null ");
    name = null;
    vn = v;
    //depth = v.getCurrentDepth();
    iter_type = UNDEFINED; // not defined
    ft = true;
    size = 0;
    special = false;
    xpe = null;
    symbolHash = new Hashtable();
    fib = null;
    enableCaching = true;
    //fib = new FastIntBuffer(4);
    //p = null;   
    //count=0;
}

/**
 * Use this constructor for delayed binding to VTDNav
 * which allows the reuse of XPath expression 
 *
 */
public AutoPilot(){
    name = null;
    //vn = v;
    //depth = v.getCurrentDepth();
    iter_type = UNDEFINED; // not defined
    ft = true;
    size = 0;
    special = false;
    xpe = null;
    symbolHash = new Hashtable();
    fib = null;
    enableCaching = true;
    //count=0;
}
/** This function creates URL ns prefix 
 *  and is intended to be called prior to selectXPath
 *  @param prefix
 *  @param URL
 */

final public void declareXPathNameSpace(String prefix, String URL){
    if (nsHash==null)
        nsHash = new Hashtable();
    nsHash.put(prefix, URL);
    //System.out.println(ht); 
}

/**
 * Bind is to replace rebind() and setVTDNav()
 * It resets the internal state of AutoPilot
 * so one can attach a VTDNav object to the autopilot
 * @param vnv
 *
 */
public void bind (VTDNav vnv){
    name = null;
    if (vnv == null)
        throw new IllegalArgumentException(" instance of VTDNav can't be null ");
    vn = vnv;
    //depth = v.getCurrentDepth();
    iter_type = UNDEFINED; // not defined
    ft = true;
    size = 0;
    special = false;
    //count = 0;
    //resetXPath();
}

/**
 * Register the binding between a variableExpr name and variableExpr expression 
 * @param varName
 * @param varExpr
 * @throws XPathParseException
 */
public void declareVariableExpr(String varName, String varExpr) throws XPathParseException {
    try{
        parser p = new parser(new StringReader(varExpr));
        p.nsHash = nsHash;
        p.symbolHash = symbolHash;
        xpe = (Expr) p.parse().value;
        symbolHash.put(varName, xpe);
        ft = true;
     }catch(XPathParseException e){
    	 System.out.println("Syntax error after or around the end of  ==>"+varExpr.substring(0,e.getOffset()));
         throw e;
     }catch(Exception e){
         throw new XPathParseException("Error occurred");
     }
 }

/**
 * Remove all declared variable expressions
 */
final public void clearVariableExprs(){
	symbolHash.clear();
}

/**
 * Remove all namespaces bindings 
 */
final public void clearXPathNameSpaces(){
	nsHash.clear();
}

public boolean iterate2() throws PilotException, NavException {
	//count++;
	//System.out.println("count-=>"+count);
	switch (iter_type) {
		case SIMPLE_NODE:
			if (ft && vn.atTerminal)
				return false;
			if (ft){
				ft =false;
				return true;
			}
			return vn.iterateNode(depth);
			
		case DESCENDANT_NODE:
			if (ft&&vn.atTerminal)
				return false;
			else{
				ft=false;
				return vn.iterateNode(depth);
			}
         	
		case FOLLOWING_NODE:
			if (ft){
				boolean b= false;
				do{
					b = vn.toNode(VTDNav.NEXT_SIBLING);
					if (b){
						ft = false;
						return true;
					}else{
						b = vn.toNode(VTDNav.PARENT);
					}
				}while(b);
				return false;
			}			
			return vn.iterate_following_node();
			
		case PRECEDING_NODE:
			if(ft){
				ft = false;
				vn.toNode(VTDNav.ROOT);
				vn.toNode(VTDNav.P);	
			}
			return vn.iterate_preceding_node(contextCopy,endIndex);
		//case 
		default :
			throw new PilotException(" iteration action type undefined");
	}
}
/**
 * Iterate over all the selected element nodes in document order.
 * Null element name allowed, corresponding to node() in xpath
 * Creation date: (12/4/03 5:25:42 PM)
 * @return boolean
 * @exception com.ximpleware.NavException See description in method toElement() in VTDNav class.
 */
public boolean iterate() throws PilotException, NavException {
	//count++;
	//System.out.println("count-=>"+count);
    switch (iter_type) {
        case SIMPLE :
        	//System.out.println("iterating ---> "+name+ " depth ---> "+depth);
            /*if (elementName == null)
                throw new PilotException(" Element name not set ");*/
        	if (vn.atTerminal)
        	    return false;
            if (ft == false)
                return vn.iterate(depth, name, special);
            else {
            	ft = false;
                if (special || 
                		vn.matchElement(name)) {                	
                    return true;
                } else
                    return vn.iterate(depth, name, special);
            }
            
        case SIMPLE_NS :
        	if (vn.atTerminal)
        	    return false;
            if (ft == false)
                return vn.iterateNS(depth, URL, localName);
            else {
            	ft = false;
                if (vn.matchElementNS(URL, localName)) {
                	return true;
                } else
                    return vn.iterateNS(depth, URL, localName);
            }
            
         case DESCENDANT:
         	if (vn.atTerminal)
         	    return false;
         	return vn.iterate(depth, name, special);
         	
         case DESCENDANT_NS:
         	if (vn.atTerminal)
         	    return false;         	
         	return vn.iterateNS(depth, URL, localName);
         	
         case FOLLOWING:
         	if (vn.atTerminal)
         	    return false;
            if (ft == false)
                return vn.iterate_following(name, special);
            else {
            	ft = false;
            	// find the first next sibling of 
            	while(true){
            		while (vn.toElement(VTDNav.NS)){
            			 if (special || vn.matchElement(name)) {                	
                            return true;
            			 }
            			 return vn.iterate_following(name, special);
            		}
                    if (vn.toElement(VTDNav.P)==false){
                    	//return vn.iterate_following(name, special);
                        return false;
                    } 
            	}
            }
            
         case FOLLOWING_NS:
         	if (vn.atTerminal)
         	    return false;
         	if (ft == false)
                return vn.iterate_followingNS(URL,localName);
            else {
            	ft = false;
            	// find the first next sibling of 
            	while(true){
            		while (vn.toElement(VTDNav.NS)){
            			 if (vn.matchElementNS(URL,localName)) {                	
                            return true;
            			 }
            			 return vn.iterate_followingNS(URL,localName);
            		}
                    if (vn.toElement(VTDNav.P)==false){
                    	return false;
                    } 
            	}
            }
           
         case PRECEDING: 
         	if (vn.atTerminal)
         	    return false;
         	if(ft){
         		ft = false;
         		vn.toElement(VTDNav.ROOT);
         	}
         	return vn.iterate_preceding(name, contextCopy,endIndex);

         case PRECEDING_NS:
         	if (vn.atTerminal)
         	    return false;
         	if(ft){
         		ft = false;
         		vn.toElement(VTDNav.ROOT);
         	}
         	return vn.iterate_precedingNS(URL,localName,contextCopy,endIndex);
         	

        default :
            throw new PilotException(" iteration action type undefined");
    }
}

/**
 * This method implements the namespace axis for XPath
 * @return
 * @throws PilotException
 * @throws NavException
 */
	protected int iterateNameSpace() throws PilotException, NavException {
		if (vn.ns == false)
			return -1;
		if (ft != false) {
			ft = false;
			index = vn.getCurrentIndex2() + 1;
		} else
			index += 2;

		while (index < size) {
			int type = vn.getTokenType(index);
			if (type == VTDNav.TOKEN_ATTR_NAME || type == VTDNav.TOKEN_ATTR_NS) {
				if (type == VTDNav.TOKEN_ATTR_NS){ 
				    if  (name.equals("*")  
				    		|| vn.matchRawTokenString(index, name2)
				    ){
				    	// check to see if the namespace has appeared before
				    	if (checkNsUniqueness(index)){
				    		vn.LN = index;
				    		vn.atTerminal = true;
				    		return index;
				    	}
				    }
				} 
				index += 2;
			} else {
				vn.atTerminal = false;
				if (vn.toElement(VTDNav.P) == false) {
					return -1;
				} else {
					index = vn.getCurrentIndex2() + 1;
				}
			}
		}

		return -1;
	}
	
	protected boolean checkNsUniqueness(int i) throws NavException{
		for (int j=0;j"+s.substring(0,e.getOffset()));
        throw e;
    }catch(Exception e){
        throw new XPathParseException("Error occurred");
    }
}

/**
 * Reset the XPath so the XPath Expression can 
 * be reused and revaluated in anther context position
 *
 */

final public void resetXPath(){
	if (xpe!=null && vn!=null){
		xpe.reset(vn);
		ft = true;
		vn.contextStack2.size = stackSize;
		if (enableCaching)
			xpe.clearCache();
	}
}
/**
 * evalXPathToNumber() evaluates the xpath expression to a double
 * @return double
 *
 */
final public double evalXPathToNumber(){
    return xpe.evalNumber(vn);
}
/**
 * evalXPathToString() evaluates the xpath expression to a String
 * @return String
 *
 */
final public String evalXPathToString(){
    return xpe.evalString(vn);
}
/**
 * evalXPathToBoolean() evaluates the xpath expression to a boolean
 * @return boolean
 *
 */
final public boolean evalXPathToBoolean(){
    return xpe.evalBoolean(vn);
}
/**
 * This method returns the next node in the nodeset
 * it returns -1 if there is no more node
 * Afer finishing evaluating, don't forget to  reset the xpath 
 * @return int corresponding to the VTD index
 */
public int evalXPath() throws XPathEvalException, NavException{
	if (xpe!=null){
	    if (ft == true){
	        if (vn != null){
	            stackSize = vn.contextStack2.size;
	        }
			ft = false;
    		xpe.adjust(vn.getTokenCount());
	    }
	   
		return xpe.evalNodeSet(vn);
	}
	throw new PilotException(" Null XPath expression "); 
}

/**
 * Setspecial is used by XPath evaluator to distinguish between
 * node() and *
 * node() corresponding to b= true;
 * @param b
 */

final protected void setSpecial(boolean b ){
	special = b;
}

/**
 * Convert the expression to a string
 * For debugging purpose
 * @return String
 */
final public String getExprString(){
	return xpe.toString();
}
/**
 * set state to false to disable caching, which by default is enabled
 * @param state
 */
final public void enableCaching(boolean state){
	enableCaching = state;
}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy