KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > xpath > Env


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.xpath;
30
31 import com.caucho.util.FreeList;
32 import com.caucho.xml.XmlUtil;
33 import com.caucho.xpath.expr.ObjectVar;
34 import com.caucho.xpath.expr.Var;
35 import com.caucho.xpath.pattern.AbstractPattern;
36 import com.caucho.xpath.pattern.NodeIterator;
37
38 import org.w3c.dom.Document JavaDoc;
39 import org.w3c.dom.Element JavaDoc;
40 import org.w3c.dom.Node JavaDoc;
41
42 import java.util.ArrayList JavaDoc;
43 import java.util.HashMap JavaDoc;
44 import java.util.Iterator JavaDoc;
45
46 /**
47  * Global and local variable environment. The April XSLT draft introduces
48  * global and local variables. The Env class contains those bindings.
49  *
50  * <p>Because this class exists only to support XSL, it makes a number
51  * of assumptions that would be invalid for a typical API. Specifically,
52  * the variable names <font color='red'>must</font> be interned strings, i.e.
53  * variable matching uses '==', not equals.
54  *
55  * <p>Local variables are handled like a stack. They are pushed and
56  * popped as necessary. The top variables shadow bottom variables.
57  *
58  * <p>In other words, although the API somewhat resembles a HashMap,
59  * it can't be used as a generic hash map.
60  */

61 public class Env implements ExprEnvironment {
62   static FreeList<Env> _freeList = new FreeList<Env>(32);
63   
64   HashMap JavaDoc _ids;
65   HashMap JavaDoc _idCache;
66   Element JavaDoc _lastElement;
67   HashMap JavaDoc<String JavaDoc,Var> _globals; // = new HashMap();
68
HashMap JavaDoc _functions;
69   HashMap JavaDoc _cache;
70
71   String JavaDoc []_varKeys;
72   Var []_varValues;
73   int _varSize;
74
75   private Node JavaDoc _currentNode;
76   private Node JavaDoc _contextNode;
77   
78   private int _positionIndex;
79   private boolean _hasMorePositions;
80   private int _useCount;
81   
82   private Env _parent;
83   private Env _root;
84
85   private ExprEnvironment _exprEnv;
86   private AbstractPattern _select;
87
88   private int _position;
89   private int _size;
90
91   private StylesheetEnv _stylesheetEnv;
92   private VarEnv _varEnv;
93
94   static Env create()
95   {
96     Env env = null; // (Env) freeList.allocate();
97
if (env == null)
98       env = new Env();
99
100     env._root = env;
101     
102     return env;
103   }
104
105   public void setStylesheetEnv(StylesheetEnv stylesheetEnv)
106   {
107     _stylesheetEnv = stylesheetEnv;
108   }
109
110   public StylesheetEnv getStylesheetEnv()
111   {
112     for (Env env = this; env != null; env = env._parent)
113       if (env._stylesheetEnv != null)
114     return env._stylesheetEnv;
115
116     return null;
117   }
118
119   /**
120    * Sets the variable environment.
121    */

122   public void setVarEnv(VarEnv varEnv)
123   {
124     _varEnv = varEnv;
125   }
126
127   /**
128    * Returns the variable environment.
129    */

130   public VarEnv getVarEnv()
131   {
132     return _varEnv;
133   }
134
135   /**
136    * Initialize the XPath environment with values from the parent.
137    */

138   void init(Env parent)
139   {
140     _parent = parent;
141     _root = parent._root;
142   }
143
144   /**
145    * Initialize the XPath environment with a context and a select node.
146    */

147   void init(Env parent, AbstractPattern select, Node JavaDoc currentNode)
148   {
149     _parent = parent;
150     _root = parent._root;
151     _select = select;
152     _currentNode = currentNode;
153   }
154
155   /**
156    * Initialize the XPath environment with values from the parent.
157    */

158   void initMacro(Env parent)
159   {
160     _parent = parent;
161     _root = parent._root;
162     
163     _select = parent._select;
164     _stylesheetEnv = parent._stylesheetEnv;
165     _exprEnv = parent._exprEnv;
166     _currentNode = parent._currentNode;
167     _contextNode = parent._contextNode;
168     
169     _position = parent._position;
170     _size = parent._size;
171   
172     _positionIndex = 0;
173     _hasMorePositions = false;
174     _useCount = 0;
175   }
176
177   /**
178    * Clears all values in the local environment.
179    */

180   public void clear()
181   {
182     if (true)
183       return;
184     
185     _useCount++;
186     if (_ids != null) {
187       _ids.clear();
188       _idCache.clear();
189     }
190
191     while (_varSize-- > 0) {
192       _varKeys[_varSize] = null;
193       _varValues[_varSize] = null;
194     }
195     _varSize = 0;
196
197     _lastElement = null;
198     _globals.clear();
199     _functions = null;
200     _cache = null;
201     _currentNode = null;
202     _contextNode = null;
203     _parent = null;
204     _select = null;
205
206     _size = 0;
207     _position = 0;
208     _positionIndex = 0;
209     _hasMorePositions = false;
210   }
211
212   /**
213    * Returns the parent envivonment.
214    */

215   Env getParent()
216   {
217     return _parent;
218   }
219
220   /**
221    * Returns the current number of local variables.
222    */

223   public int getVarSize()
224   {
225     return _varSize;
226   }
227
228   /**
229    * Sets the current number of local variables (popping, them).
230    */

231   public void setVarSize(int size)
232   {
233     if (_varKeys == null)
234       return;
235
236     for (; _varSize > size; _varSize--) {
237       _varSize--;
238       _varKeys[_varSize] = null;
239       _varValues[_varSize] = null;
240     }
241   }
242
243   /**
244    * Returns the value associated with name.
245    *
246    * <p><em>name must be interned</em>
247    */

248   public Var getVar(String JavaDoc name)
249   {
250     for (int i = _varSize - 1; i >= 0; i--) {
251       if (_varKeys[i] == name)
252     return _varValues[i];
253     }
254
255     if (_root._globals != null) {
256       Var var = _root._globals.get(name);
257
258       if (var != null)
259         return var;
260     }
261
262     if (_root._varEnv != null)
263       return _root._varEnv.getVar(name);
264     else
265       return null;
266   }
267
268   /**
269    * Adds the value associated with name.
270    *
271    * <p><em>name must be interned</em>
272    */

273   public int addVar(String JavaDoc name, Object JavaDoc value)
274   {
275     _useCount++;
276     if (value instanceof Iterator)
277       value = iteratorToList((Iterator) value);
278
279     if (! (value instanceof Var))
280       value = new ObjectVar(value);
281     
282     return addVar(name, (Var) value);
283   }
284   
285   /**
286    * Sets the value associated with name.
287    *
288    * <p><em>name must be interned</em>
289    */

290   public void setVar(String JavaDoc name, Object JavaDoc value)
291   {
292     _useCount++;
293     if (value instanceof Iterator)
294       value = iteratorToList((Iterator) value);
295
296     if (! (value instanceof Var))
297       value = new ObjectVar(value);
298
299     for (int i = _varSize - 1; i >= 0; i--) {
300       if (_varKeys[i] == name) {
301         _varValues[i] = (Var) value;
302         return;
303       }
304     }
305
306     addVar(name, (Var) value);
307   }
308
309   /**
310    * Adds the value associated with name.
311    *
312    * <p><em>name must be interned</em>
313    */

314   public int addVar(String JavaDoc name, Var value)
315   {
316     _useCount++;
317
318     if (_varKeys == null) {
319       _varKeys = new String JavaDoc[16];
320       _varValues = new Var[16];
321     }
322     else if (_varSize == _varKeys.length) {
323       String JavaDoc []newKeys = new String JavaDoc[2 * _varKeys.length];
324       Var []newValues = new Var[2 * _varKeys.length];
325
326       System.arraycopy(_varKeys, 0, newKeys, 0, _varSize);
327       System.arraycopy(_varValues, 0, newValues, 0, _varSize);
328
329       _varKeys = newKeys;
330       _varValues = newValues;
331     }
332
333     _varKeys[_varSize] = name;
334     _varValues[_varSize] = value;
335     _varSize++;
336
337     return _varSize - 1;
338   }
339
340   /**
341    * Pops the last count vars from the local stack.
342    */

343   public void popVars(int count)
344   {
345     _useCount++;
346     if (_varKeys == null)
347       return;
348
349     for (; count > 0 && _varSize > 0; count--) {
350       _varSize--;
351       _varKeys[_varSize] = null;
352       _varValues[_varSize].free();
353       _varValues[_varSize] = null;
354     }
355   }
356
357   /**
358    * Returns the top of the stack.
359    */

360   public int getTop()
361   {
362     return _varSize;
363   }
364   
365   /**
366    * Pops the last count vars from the local stack.
367    */

368   public void popToTop(int top)
369   {
370     _useCount++;
371     if (_varKeys == null)
372       return;
373
374     while (top < _varSize) {
375       _varSize--;
376       _varKeys[_varSize] = null;
377       _varValues[_varSize].free();
378       _varValues[_varSize] = null;
379     }
380   }
381
382   /**
383    * Sets a global variable.
384    */

385   public void setGlobal(String JavaDoc name, Object JavaDoc value)
386   {
387     _useCount++;
388     
389     Var var = null;
390     
391     if (value instanceof Iterator)
392       value = iteratorToList((Iterator) value);
393
394     if (value instanceof Var)
395       var = (Var) value;
396     else
397       var = new ObjectVar(value);
398
399     if (_root._globals == null)
400       _root._globals = new HashMap JavaDoc<String JavaDoc,Var>();
401     
402     _root._globals.put(name, var);
403   }
404
405   /**
406    * Converts an iterator to an array list
407    */

408   private ArrayList JavaDoc iteratorToList(Iterator iter)
409   {
410     ArrayList JavaDoc list = new ArrayList JavaDoc();
411     while (iter.hasNext())
412       list.add(iter.next());
413
414     return list;
415   }
416
417   /**
418    * Sets the extension function library
419    *
420    * @param function new function library
421    * @return old function library
422    */

423   public HashMap JavaDoc setFunctions(HashMap JavaDoc functions)
424   {
425     HashMap JavaDoc old = _functions;
426
427     _functions = functions;
428
429     return old;
430   }
431   
432   /**
433    * Adds and extension function
434    *
435    * @param function new function library
436    * @return old function library
437    */

438   public void addFunction(String JavaDoc name, Object JavaDoc fun)
439   {
440     if (_functions == null)
441       _functions = new HashMap JavaDoc();
442
443     _functions.put(name, fun);
444   }
445
446   /**
447    * Returns the named function.
448    */

449   public XPathFun getFunction(String JavaDoc name)
450   {
451     if (_root._functions == null)
452       return null;
453     else
454       return (XPathFun) _root._functions.get(name);
455   }
456
457   /**
458    * Returns true if there are more positions() needed to iterate through.
459    */

460   public boolean hasMorePositions()
461   {
462     return _hasMorePositions;
463   }
464   /**
465    * Set true if there are more positions() needed to iterate through.
466    *
467    * @param more if true, there are more positions to iterate through.
468    *
469    * @return the old more-position value.
470    */

471   public boolean setMorePositions(boolean more)
472   {
473     boolean old = _hasMorePositions;
474
475     _hasMorePositions = more;
476
477     return old;
478   }
479   /*
480    * The position index is used for patterns which have multiple position()s
481    * for the same node. See FilterPattern for a more detailed description.
482    *
483    * @param index the new position index.
484    *
485    * @return the old position index.
486    */

487   public int setPositionIndex(int index)
488   {
489     int old = _positionIndex;
490
491     _positionIndex = index;
492
493     return old;
494   }
495   
496   /*
497    * Returns the position index is used for patterns which have
498    * multiple position()s for the same node. See FilterPattern for a
499    * more detailed description.
500    */

501   public int getPositionIndex()
502   {
503     return _positionIndex;
504   }
505
506   /**
507    * Gets the current node.
508    */

509   public Node JavaDoc getCurrentNode()
510   {
511     return _currentNode;
512   }
513
514   /**
515    * Sets the current node.
516    */

517   public void setCurrentNode(Node JavaDoc node)
518   {
519     _currentNode = node;
520   }
521
522   /**
523    * Sets the selection context
524    */

525   public AbstractPattern setSelect(Node JavaDoc node, AbstractPattern select)
526   {
527     AbstractPattern oldSelect = _select;
528     
529     _contextNode = node;
530     _select = select;
531
532     _position = 0;
533
534     return oldSelect;
535   }
536
537   public AbstractPattern getSelect()
538   {
539     return _select;
540   }
541
542   /**
543    * Sets the selection context
544    */

545   public ExprEnvironment setExprEnv(ExprEnvironment exprEnv)
546   {
547     ExprEnvironment oldExprEnv = _exprEnv;
548     
549     _exprEnv = exprEnv;
550
551     return oldExprEnv;
552   }
553
554   public ExprEnvironment getExprEnv()
555   {
556     return _exprEnv;
557   }
558
559   /**
560    * Gets the context node.
561    */

562   public Node JavaDoc getContextNode()
563   {
564     return _contextNode;
565   }
566
567   /**
568    * Sets the context node.
569    */

570   public Node JavaDoc setContextNode(Node JavaDoc contextNode)
571   {
572     Node JavaDoc oldNode = _contextNode;
573     _contextNode = contextNode;
574     return oldNode;
575   }
576
577   /**
578    * Returns the position of the context node.
579    */

580   public int getContextPosition()
581   {
582     if (_exprEnv != null)
583       return _exprEnv.getContextPosition();
584     
585     if (_position > 0)
586       return _position;
587
588     if (_contextNode == null || _currentNode == null)
589       return 0;
590
591     if (_select != null) {
592       try {
593         NodeIterator iter = _select.select(_contextNode, this);
594         Node JavaDoc child;
595       
596         while ((child = iter.nextNode()) != null && child != _currentNode) {
597         }
598
599         return iter.getContextPosition();
600       } catch (Exception JavaDoc e) {
601       }
602     }
603
604     Node JavaDoc child = _contextNode.getFirstChild();
605     int pos = 1;
606     for (;
607          child != null && child != _currentNode;
608          child = child.getNextSibling()) {
609       pos++;
610     }
611     
612     return pos;
613   }
614
615   /**
616    * Returns the number of nodes in the context list.
617    */

618   public int getContextSize()
619   {
620     if (_exprEnv != null)
621       return _exprEnv.getContextSize();
622     
623     if (_size > 0)
624       return _size;
625     
626     if (_contextNode == null || _currentNode == null)
627       return 0;
628
629     if (_select != null) {
630       try {
631         NodeIterator iter = _select.select(_contextNode, this);
632         Node JavaDoc child;
633       
634         while ((child = iter.nextNode()) != null && child != _currentNode) {
635         }
636
637         return iter.getContextSize();
638       } catch (Exception JavaDoc e) {
639       }
640     }
641
642     Node JavaDoc child = _contextNode.getFirstChild();
643     int pos = 0;
644     for (;
645          child != null;
646          child = child.getNextSibling())
647       pos++;
648     
649     return pos;
650   }
651
652   /**
653    * Returns a document for creating nodes.
654    */

655   public Document JavaDoc getOwnerDocument()
656   {
657     return null;
658   }
659
660   /**
661    * Returns the given system property.
662    */

663   public Object JavaDoc systemProperty(String JavaDoc namespaceURI, String JavaDoc localName)
664   {
665     return null;
666   }
667
668   /**
669    * Returns the string-value of the node.
670    */

671   public String JavaDoc stringValue(Node JavaDoc node)
672   {
673     return XmlUtil.textValue(node);
674   }
675   
676   /*
677    * Returns the position() value. Note, this is not the same as
678    * positionIndex.
679    */

680   public void setPosition(int position)
681   {
682     _position = position;
683   }
684   
685   public int setContextPosition(int position)
686   {
687     int oldPosition = _position;
688     _position = position;
689     return oldPosition;
690   }
691
692   /**
693    * Sets the context size to a know value.
694    */

695   public int setContextSize(int size)
696   {
697     int oldSize = _size;
698     _size = size;
699     return oldSize;
700   }
701
702   public Object JavaDoc getCache(Object JavaDoc key)
703   {
704     if (_root._cache == null)
705       return null;
706     else
707       return _root._cache.get(key);
708   }
709
710   public void setCache(Object JavaDoc key, Object JavaDoc value)
711   {
712     if (_root._cache == null)
713       _root._cache = new HashMap JavaDoc();
714
715     _root._cache.put(key, value);
716   }
717
718   public int getUseCount()
719   {
720     return _useCount;
721   }
722
723   public void free()
724   {
725     _root = null;
726     _parent = null;
727     _select = null;
728
729     _exprEnv = null;
730     _stylesheetEnv = null;
731     
732     if (_ids != null) {
733       _ids.clear();
734       _idCache.clear();
735     }
736
737     while (_varSize-- > 0) {
738       _varKeys[_varSize] = null;
739       _varValues[_varSize] = null;
740     }
741     _varSize = 0;
742
743     _lastElement = null;
744     if (_globals != null)
745       _globals.clear();
746     _functions = null;
747     _cache = null;
748     _currentNode = null;
749     _contextNode = null;
750
751     _size = 0;
752     _position = 0;
753     _positionIndex = 0;
754     _hasMorePositions = false;
755
756     _freeList.free(this);
757   }
758 }
759
Popular Tags