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

com.caucho.xpath.Env Maven / Gradle / Ivy

/*
 * Copyright (c) 1998-2012 Caucho Technology -- all rights reserved
 *
 * This file is part of Resin(R) Open Source
 *
 * Each copy or derived work must preserve the copyright notice and this
 * notice unmodified.
 *
 * Resin Open Source 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.
 *
 * Resin Open Source 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, or any warranty
 * of NON-INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Resin Open Source; if not, write to the
 *   Free SoftwareFoundation, Inc.
 *   59 Temple Place, Suite 330
 *   Boston, MA 02111-1307  USA
 *
 * @author Scott Ferguson
 */

package com.caucho.xpath;

import com.caucho.util.FreeList;
import com.caucho.xml.XmlUtil;
import com.caucho.xpath.expr.ObjectVar;
import com.caucho.xpath.expr.Var;
import com.caucho.xpath.pattern.AbstractPattern;
import com.caucho.xpath.pattern.NodeIterator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

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

/**
 * Global and local variable environment.  The April XSLT draft introduces
 * global and local variables.  The Env class contains those bindings.
 *
 * 

Because this class exists only to support XSL, it makes a number * of assumptions that would be invalid for a typical API. Specifically, * the variable names must be interned strings, i.e. * variable matching uses '==', not equals. * *

Local variables are handled like a stack. They are pushed and * popped as necessary. The top variables shadow bottom variables. * *

In other words, although the API somewhat resembles a HashMap, * it can't be used as a generic hash map. */ public class Env implements ExprEnvironment { static FreeList _freeList = new FreeList(32); HashMap _ids; HashMap _idCache; Element _lastElement; HashMap _globals; // = new HashMap(); HashMap _functions; HashMap _cache; String []_varKeys; Var []_varValues; int _varSize; private Node _currentNode; private Node _contextNode; private int _positionIndex; private boolean _hasMorePositions; private int _useCount; private Env _parent; private Env _root; private ExprEnvironment _exprEnv; private AbstractPattern _select; private int _position; private int _size; private StylesheetEnv _stylesheetEnv; private VarEnv _varEnv; static Env create() { Env env = null; // (Env) freeList.allocate(); if (env == null) env = new Env(); env._root = env; return env; } public void setStylesheetEnv(StylesheetEnv stylesheetEnv) { _stylesheetEnv = stylesheetEnv; } public StylesheetEnv getStylesheetEnv() { for (Env env = this; env != null; env = env._parent) if (env._stylesheetEnv != null) return env._stylesheetEnv; return null; } /** * Sets the variable environment. */ public void setVarEnv(VarEnv varEnv) { _varEnv = varEnv; } /** * Returns the variable environment. */ public VarEnv getVarEnv() { return _varEnv; } /** * Initialize the XPath environment with values from the parent. */ void init(Env parent) { _parent = parent; _root = parent._root; } /** * Initialize the XPath environment with a context and a select node. */ void init(Env parent, AbstractPattern select, Node currentNode) { _parent = parent; _root = parent._root; _select = select; _currentNode = currentNode; } /** * Initialize the XPath environment with values from the parent. */ void initMacro(Env parent) { _parent = parent; _root = parent._root; _select = parent._select; _stylesheetEnv = parent._stylesheetEnv; _exprEnv = parent._exprEnv; _currentNode = parent._currentNode; _contextNode = parent._contextNode; _position = parent._position; _size = parent._size; _positionIndex = 0; _hasMorePositions = false; _useCount = 0; } /** * Clears all values in the local environment. */ public void clear() { if (true) return; _useCount++; if (_ids != null) { _ids.clear(); _idCache.clear(); } while (_varSize-- > 0) { _varKeys[_varSize] = null; _varValues[_varSize] = null; } _varSize = 0; _lastElement = null; _globals.clear(); _functions = null; _cache = null; _currentNode = null; _contextNode = null; _parent = null; _select = null; _size = 0; _position = 0; _positionIndex = 0; _hasMorePositions = false; } /** * Returns the parent envivonment. */ Env getParent() { return _parent; } /** * Returns the current number of local variables. */ public int getVarSize() { return _varSize; } /** * Sets the current number of local variables (popping, them). */ public void setVarSize(int size) { if (_varKeys == null) return; for (; _varSize > size; _varSize--) { _varSize--; _varKeys[_varSize] = null; _varValues[_varSize] = null; } } /** * Returns the value associated with name. * *

name must be interned */ public Var getVar(String name) { for (int i = _varSize - 1; i >= 0; i--) { if (_varKeys[i] == name) return _varValues[i]; } if (_root._globals != null) { Var var = _root._globals.get(name); if (var != null) return var; } if (_root._varEnv != null) return _root._varEnv.getVar(name); else return null; } /** * Adds the value associated with name. * *

name must be interned */ public int addVar(String name, Object value) { _useCount++; if (value instanceof Iterator) value = iteratorToList((Iterator) value); if (! (value instanceof Var)) value = new ObjectVar(value); return addVar(name, (Var) value); } /** * Sets the value associated with name. * *

name must be interned */ public void setVar(String name, Object value) { _useCount++; if (value instanceof Iterator) value = iteratorToList((Iterator) value); if (! (value instanceof Var)) value = new ObjectVar(value); for (int i = _varSize - 1; i >= 0; i--) { if (_varKeys[i] == name) { _varValues[i] = (Var) value; return; } } addVar(name, (Var) value); } /** * Adds the value associated with name. * *

name must be interned */ public int addVar(String name, Var value) { _useCount++; if (_varKeys == null) { _varKeys = new String[16]; _varValues = new Var[16]; } else if (_varSize == _varKeys.length) { String []newKeys = new String[2 * _varKeys.length]; Var []newValues = new Var[2 * _varKeys.length]; System.arraycopy(_varKeys, 0, newKeys, 0, _varSize); System.arraycopy(_varValues, 0, newValues, 0, _varSize); _varKeys = newKeys; _varValues = newValues; } _varKeys[_varSize] = name; _varValues[_varSize] = value; _varSize++; return _varSize - 1; } /** * Pops the last count vars from the local stack. */ public void popVars(int count) { _useCount++; if (_varKeys == null) return; for (; count > 0 && _varSize > 0; count--) { _varSize--; _varKeys[_varSize] = null; _varValues[_varSize].free(); _varValues[_varSize] = null; } } /** * Returns the top of the stack. */ public int getTop() { return _varSize; } /** * Pops the last count vars from the local stack. */ public void popToTop(int top) { _useCount++; if (_varKeys == null) return; while (top < _varSize) { _varSize--; _varKeys[_varSize] = null; _varValues[_varSize].free(); _varValues[_varSize] = null; } } /** * Sets a global variable. */ public void setGlobal(String name, Object value) { _useCount++; Var var = null; if (value instanceof Iterator) value = iteratorToList((Iterator) value); if (value instanceof Var) var = (Var) value; else var = new ObjectVar(value); if (_root._globals == null) _root._globals = new HashMap(); _root._globals.put(name, var); } /** * Converts an iterator to an array list */ private ArrayList iteratorToList(Iterator iter) { ArrayList list = new ArrayList(); while (iter.hasNext()) list.add(iter.next()); return list; } /** * Sets the extension function library * * @param function new function library * @return old function library */ public HashMap setFunctions(HashMap functions) { HashMap old = _functions; _functions = functions; return old; } /** * Adds and extension function * * @param function new function library * @return old function library */ public void addFunction(String name, Object fun) { if (_functions == null) _functions = new HashMap(); _functions.put(name, fun); } /** * Returns the named function. */ public XPathFun getFunction(String name) { if (_root._functions == null) return null; else return (XPathFun) _root._functions.get(name); } /** * Returns true if there are more positions() needed to iterate through. */ public boolean hasMorePositions() { return _hasMorePositions; } /** * Set true if there are more positions() needed to iterate through. * * @param more if true, there are more positions to iterate through. * * @return the old more-position value. */ public boolean setMorePositions(boolean more) { boolean old = _hasMorePositions; _hasMorePositions = more; return old; } /* * The position index is used for patterns which have multiple position()s * for the same node. See FilterPattern for a more detailed description. * * @param index the new position index. * * @return the old position index. */ public int setPositionIndex(int index) { int old = _positionIndex; _positionIndex = index; return old; } /* * Returns the position index is used for patterns which have * multiple position()s for the same node. See FilterPattern for a * more detailed description. */ public int getPositionIndex() { return _positionIndex; } /** * Gets the current node. */ public Node getCurrentNode() { return _currentNode; } /** * Sets the current node. */ public void setCurrentNode(Node node) { _currentNode = node; } /** * Sets the selection context */ public AbstractPattern setSelect(Node node, AbstractPattern select) { AbstractPattern oldSelect = _select; _contextNode = node; _select = select; _position = 0; return oldSelect; } public AbstractPattern getSelect() { return _select; } /** * Sets the selection context */ public ExprEnvironment setExprEnv(ExprEnvironment exprEnv) { ExprEnvironment oldExprEnv = _exprEnv; _exprEnv = exprEnv; return oldExprEnv; } public ExprEnvironment getExprEnv() { return _exprEnv; } /** * Gets the context node. */ public Node getContextNode() { return _contextNode; } /** * Sets the context node. */ public Node setContextNode(Node contextNode) { Node oldNode = _contextNode; _contextNode = contextNode; return oldNode; } /** * Returns the position of the context node. */ public int getContextPosition() { if (_exprEnv != null) return _exprEnv.getContextPosition(); if (_position > 0) return _position; if (_contextNode == null || _currentNode == null) return 0; if (_select != null) { try { NodeIterator iter = _select.select(_contextNode, this); Node child; while ((child = iter.nextNode()) != null && child != _currentNode) { } return iter.getContextPosition(); } catch (Exception e) { } } Node child = _contextNode.getFirstChild(); int pos = 1; for (; child != null && child != _currentNode; child = child.getNextSibling()) { pos++; } return pos; } /** * Returns the number of nodes in the context list. */ public int getContextSize() { if (_exprEnv != null) return _exprEnv.getContextSize(); if (_size > 0) return _size; if (_contextNode == null || _currentNode == null) return 0; if (_select != null) { try { NodeIterator iter = _select.select(_contextNode, this); Node child; while ((child = iter.nextNode()) != null && child != _currentNode) { } return iter.getContextSize(); } catch (Exception e) { } } Node child = _contextNode.getFirstChild(); int pos = 0; for (; child != null; child = child.getNextSibling()) pos++; return pos; } /** * Returns a document for creating nodes. */ public Document getOwnerDocument() { return null; } /** * Returns the given system property. */ public Object systemProperty(String namespaceURI, String localName) { return null; } /** * Returns the string-value of the node. */ public String stringValue(Node node) { return XmlUtil.textValue(node); } /* * Returns the position() value. Note, this is not the same as * positionIndex. */ public void setPosition(int position) { _position = position; } public int setContextPosition(int position) { int oldPosition = _position; _position = position; return oldPosition; } /** * Sets the context size to a know value. */ public int setContextSize(int size) { int oldSize = _size; _size = size; return oldSize; } public Object getCache(Object key) { if (_root._cache == null) return null; else return _root._cache.get(key); } public void setCache(Object key, Object value) { if (_root._cache == null) _root._cache = new HashMap(); _root._cache.put(key, value); } public int getUseCount() { return _useCount; } public void free() { _root = null; _parent = null; _select = null; _exprEnv = null; _stylesheetEnv = null; if (_ids != null) { _ids.clear(); _idCache.clear(); } while (_varSize-- > 0) { _varKeys[_varSize] = null; _varValues[_varSize] = null; } _varSize = 0; _lastElement = null; if (_globals != null) _globals.clear(); _functions = null; _cache = null; _currentNode = null; _contextNode = null; _size = 0; _position = 0; _positionIndex = 0; _hasMorePositions = false; _freeList.free(this); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy