KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xpath > operations > Variable


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: Variable.java,v 1.22 2004/02/17 04:35:12 minchau Exp $
18  */

19 package org.apache.xpath.operations;
20
21 import javax.xml.transform.TransformerException JavaDoc;
22
23 import org.apache.xalan.res.XSLMessages;
24 import org.apache.xml.utils.QName;
25 import org.apache.xpath.Expression;
26 import org.apache.xpath.ExpressionOwner;
27 import org.apache.xpath.XPath;
28 import org.apache.xpath.XPathContext;
29 import org.apache.xpath.XPathVisitor;
30 import org.apache.xpath.axes.PathComponent;
31 import org.apache.xpath.axes.WalkerFactory;
32 import org.apache.xpath.objects.XNodeSet;
33 import org.apache.xpath.objects.XObject;
34 import org.apache.xpath.res.XPATHErrorResources;
35
36
37 /**
38  * The variable reference expression executer.
39  */

40 public class Variable extends Expression implements PathComponent
41 {
42   /** Tell if fixupVariables was called.
43    * @serial */

44   private boolean m_fixUpWasCalled = false;
45
46   /** The qualified name of the variable.
47    * @serial */

48   protected QName m_qname;
49   
50   /**
51    * The index of the variable, which is either an absolute index to a
52    * global, or, if higher than the globals area, must be adjusted by adding
53    * the offset to the current stack frame.
54    */

55   protected int m_index;
56   
57   /**
58    * Set the index for the variable into the stack. For advanced use only. You
59    * must know what you are doing to use this.
60    *
61    * @param index a global or local index.
62    */

63   public void setIndex(int index)
64   {
65     m_index = index;
66   }
67   
68   /**
69    * Set the index for the variable into the stack. For advanced use only.
70    *
71    * @return index a global or local index.
72    */

73   public int getIndex()
74   {
75     return m_index;
76   }
77   
78   /**
79    * Set whether or not this is a global reference. For advanced use only.
80    *
81    * @param isGlobal true if this should be a global variable reference.
82    */

83   public void setIsGlobal(boolean isGlobal)
84   {
85     m_isGlobal = isGlobal;
86   }
87   
88   /**
89    * Set the index for the variable into the stack. For advanced use only.
90    *
91    * @return true if this should be a global variable reference.
92    */

93   public boolean getGlobal()
94   {
95     return m_isGlobal;
96   }
97
98   
99   
100
101   
102   protected boolean m_isGlobal = false;
103   
104   /**
105    * This function is used to fixup variables from QNames to stack frame
106    * indexes at stylesheet build time.
107    * @param vars List of QNames that correspond to variables. This list
108    * should be searched backwards for the first qualified name that
109    * corresponds to the variable reference qname. The position of the
110    * QName in the vector from the start of the vector will be its position
111    * in the stack frame (but variables above the globalsTop value will need
112    * to be offset to the current stack frame).
113    */

114   public void fixupVariables(java.util.Vector JavaDoc vars, int globalsSize)
115   {
116     m_fixUpWasCalled = true;
117     int sz = vars.size();
118
119     for (int i = vars.size()-1; i >= 0; i--)
120     {
121       QName qn = (QName)vars.elementAt(i);
122       // System.out.println("qn: "+qn);
123
if(qn.equals(m_qname))
124       {
125         
126         if(i < globalsSize)
127         {
128           m_isGlobal = true;
129           m_index = i;
130         }
131         else
132         {
133           m_index = i-globalsSize;
134         }
135           
136         return;
137       }
138     }
139     
140     java.lang.String JavaDoc msg = XSLMessages.createXPATHMessage(XPATHErrorResources.ER_COULD_NOT_FIND_VAR,
141                                              new Object JavaDoc[]{m_qname.toString()});
142                                              
143     TransformerException JavaDoc te = new TransformerException JavaDoc(msg, this);
144                                              
145     throw new org.apache.xml.utils.WrappedRuntimeException(te);
146     
147   }
148
149
150   /**
151    * Set the qualified name of the variable.
152    *
153    * @param qname Must be a non-null reference to a qualified name.
154    */

155   public void setQName(QName qname)
156   {
157     m_qname = qname;
158   }
159   
160   /**
161    * Get the qualified name of the variable.
162    *
163    * @return A non-null reference to a qualified name.
164    */

165   public QName getQName()
166   {
167     return m_qname;
168   }
169   
170   /**
171    * Execute an expression in the XPath runtime context, and return the
172    * result of the expression.
173    *
174    *
175    * @param xctxt The XPath runtime context.
176    *
177    * @return The result of the expression in the form of a <code>XObject</code>.
178    *
179    * @throws javax.xml.transform.TransformerException if a runtime exception
180    * occurs.
181    */

182   public XObject execute(XPathContext xctxt)
183     throws javax.xml.transform.TransformerException JavaDoc
184   {
185     return execute(xctxt, false);
186   }
187
188
189   /**
190    * Dereference the variable, and return the reference value. Note that lazy
191    * evaluation will occur. If a variable within scope is not found, a warning
192    * will be sent to the error listener, and an empty nodeset will be returned.
193    *
194    *
195    * @param xctxt The runtime execution context.
196    *
197    * @return The evaluated variable, or an empty nodeset if not found.
198    *
199    * @throws javax.xml.transform.TransformerException
200    */

201   public XObject execute(XPathContext xctxt, boolean destructiveOK) throws javax.xml.transform.TransformerException JavaDoc
202   {
203     org.apache.xml.utils.PrefixResolver xprefixResolver = xctxt.getNamespaceContext();
204
205     // Is the variable fetched always the same?
206
// XObject result = xctxt.getVariable(m_qname);
207
if(m_fixUpWasCalled)
208     {
209       XObject result;
210       if(m_isGlobal)
211         result = xctxt.getVarStack().getGlobalVariable(xctxt, m_index, destructiveOK);
212       else
213         result = xctxt.getVarStack().getLocalVariable(xctxt, m_index, destructiveOK);
214   
215       if (null == result)
216       {
217         // This should now never happen...
218
warn(xctxt, XPATHErrorResources.WG_ILLEGAL_VARIABLE_REFERENCE,
219              new Object JavaDoc[]{ m_qname.getLocalPart() }); //"VariableReference given for variable out "+
220
// (new RuntimeException()).printStackTrace();
221
// error(xctxt, XPATHErrorResources.ER_COULDNOT_GET_VAR_NAMED,
222
// new Object[]{ m_qname.getLocalPart() }); //"Could not get variable named "+varName);
223

224         result = new XNodeSet(xctxt.getDTMManager());
225       }
226   
227       return result;
228     }
229     else
230     {
231       // Hack city... big time. This is needed to evaluate xpaths from extensions,
232
// pending some bright light going off in my head. Some sort of callback?
233
synchronized(this)
234       {
235         org.apache.xalan.templates.ElemVariable vvar= getElemVariable();
236         if(null != vvar)
237         {
238           m_index = vvar.getIndex();
239           m_isGlobal = vvar.getIsTopLevel();
240           m_fixUpWasCalled = true;
241           return execute(xctxt);
242         }
243       }
244       throw new javax.xml.transform.TransformerException JavaDoc(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VAR_NOT_RESOLVABLE, new Object JavaDoc[]{m_qname.toString()})); //"Variable not resolvable: "+m_qname);
245
}
246   }
247   
248   /**
249    * Get the XSLT ElemVariable that this sub-expression references. In order for
250    * this to work, the SourceLocator must be the owning ElemTemplateElement.
251    * @return The dereference to the ElemVariable, or null if not found.
252    */

253   public org.apache.xalan.templates.ElemVariable getElemVariable()
254   {
255     
256     // Get the current ElemTemplateElement, and then walk backwards in
257
// document order, searching
258
// for an xsl:param element or xsl:variable element that matches our
259
// qname. If we reach the top level, use the StylesheetRoot's composed
260
// list of top level variables and parameters.
261

262     org.apache.xpath.ExpressionNode owner = getExpressionOwner();
263
264     if (null != owner && owner instanceof org.apache.xalan.templates.ElemTemplateElement)
265     {
266
267       org.apache.xalan.templates.ElemVariable vvar;
268
269       org.apache.xalan.templates.ElemTemplateElement prev =
270         (org.apache.xalan.templates.ElemTemplateElement) owner;
271
272       if (!(prev instanceof org.apache.xalan.templates.Stylesheet))
273       {
274         while ( !(prev.getParentNode() instanceof org.apache.xalan.templates.Stylesheet) )
275         {
276           org.apache.xalan.templates.ElemTemplateElement savedprev = prev;
277
278           while (null != (prev = prev.getPreviousSiblingElem()))
279           {
280             if(prev instanceof org.apache.xalan.templates.ElemVariable)
281             {
282               vvar = (org.apache.xalan.templates.ElemVariable) prev;
283             
284               if (vvar.getName().equals(m_qname))
285               {
286                 return vvar;
287               }
288             }
289           }
290           prev = savedprev.getParentElem();
291         }
292       }
293
294       vvar = prev.getStylesheetRoot().getVariableOrParamComposed(m_qname);
295       if (null != vvar)
296       {
297         return vvar;
298       }
299
300     }
301     return null;
302
303   }
304   
305   /**
306    * Tell if this expression returns a stable number that will not change during
307    * iterations within the expression. This is used to determine if a proximity
308    * position predicate can indicate that no more searching has to occur.
309    *
310    *
311    * @return true if the expression represents a stable number.
312    */

313   public boolean isStableNumber()
314   {
315     return true;
316   }
317   
318   /**
319    * Get the analysis bits for this walker, as defined in the WalkerFactory.
320    * @return One of WalkerFactory#BIT_DESCENDANT, etc.
321    */

322   public int getAnalysisBits()
323   {
324     org.apache.xalan.templates.ElemVariable vvar = getElemVariable();
325     if(null != vvar)
326     {
327         XPath xpath = vvar.getSelect();
328         if(null != xpath)
329         {
330             Expression expr = xpath.getExpression();
331             if(null != expr && expr instanceof PathComponent)
332             {
333                 return ((PathComponent)expr).getAnalysisBits();
334             }
335         }
336     }
337     return WalkerFactory.BIT_FILTER;
338   }
339
340
341   /**
342    * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
343    */

344   public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
345   {
346     visitor.visitVariableRef(owner, this);
347   }
348   /**
349    * @see Expression#deepEquals(Expression)
350    */

351   public boolean deepEquals(Expression expr)
352   {
353     if(!isSameClass(expr))
354         return false;
355         
356     if(!m_qname.equals(((Variable)expr).m_qname))
357         return false;
358         
359     // We have to make sure that the qname really references
360
// the same variable element.
361
if(getElemVariable() != ((Variable)expr).getElemVariable())
362         return false;
363         
364     return true;
365   }
366   
367   static final java.lang.String JavaDoc PSUEDOVARNAMESPACE = "http://xml.apache.org/xalan/psuedovar";
368   
369   /**
370    * Tell if this is a psuedo variable reference, declared by Xalan instead
371    * of by the user.
372    */

373   public boolean isPsuedoVarRef()
374   {
375     java.lang.String JavaDoc ns = m_qname.getNamespaceURI();
376     if((null != ns) && ns.equals(PSUEDOVARNAMESPACE))
377     {
378         if(m_qname.getLocalName().startsWith("#"))
379             return true;
380     }
381     return false;
382   }
383   
384
385 }
386
Popular Tags