KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xpath > internal > 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 package com.sun.org.apache.xpath.internal.operations;
17
18 import javax.xml.transform.TransformerException JavaDoc;
19
20 import com.sun.org.apache.xalan.internal.res.XSLMessages;
21 import com.sun.org.apache.xml.internal.utils.QName;
22 import com.sun.org.apache.xpath.internal.Expression;
23 import com.sun.org.apache.xpath.internal.ExpressionOwner;
24 import com.sun.org.apache.xpath.internal.XPath;
25 import com.sun.org.apache.xpath.internal.XPathContext;
26 import com.sun.org.apache.xpath.internal.XPathVisitor;
27 import com.sun.org.apache.xpath.internal.axes.PathComponent;
28 import com.sun.org.apache.xpath.internal.axes.WalkerFactory;
29 import com.sun.org.apache.xpath.internal.objects.XNodeSet;
30 import com.sun.org.apache.xpath.internal.objects.XObject;
31 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
32
33
34 /**
35  * The variable reference expression executer.
36  */

37 public class Variable extends Expression implements PathComponent
38 {
39   /** Tell if fixupVariables was called.
40    * @serial */

41   private boolean m_fixUpWasCalled = false;
42
43   /** The qualified name of the variable.
44    * @serial */

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

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

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

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

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

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

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

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

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

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

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

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

254 /*
255   public com.sun.org.apache.xalan.internal.templates.ElemVariable getElemVariable()
256   {
257     
258     // Get the current ElemTemplateElement, and then walk backwards in
259     // document order, searching
260     // for an xsl:param element or xsl:variable element that matches our
261     // qname. If we reach the top level, use the StylesheetRoot's composed
262     // list of top level variables and parameters.
263     
264     com.sun.org.apache.xpath.internal.ExpressionNode owner = getExpressionOwner();
265
266     if (null != owner && owner instanceof com.sun.org.apache.xalan.internal.templates.ElemTemplateElement)
267     {
268
269       com.sun.org.apache.xalan.internal.templates.ElemVariable vvar;
270
271       com.sun.org.apache.xalan.internal.templates.ElemTemplateElement prev =
272         (com.sun.org.apache.xalan.internal.templates.ElemTemplateElement) owner;
273
274       if (!(prev instanceof com.sun.org.apache.xalan.internal.templates.Stylesheet))
275       {
276         while ( !(prev.getParentNode() instanceof com.sun.org.apache.xalan.internal.templates.Stylesheet) )
277         {
278           com.sun.org.apache.xalan.internal.templates.ElemTemplateElement savedprev = prev;
279
280           while (null != (prev = prev.getPreviousSiblingElem()))
281           {
282             if(prev instanceof com.sun.org.apache.xalan.internal.templates.ElemVariable)
283             {
284               vvar = (com.sun.org.apache.xalan.internal.templates.ElemVariable) prev;
285             
286               if (vvar.getName().equals(m_qname))
287               {
288                 return vvar;
289               }
290             }
291           }
292           prev = savedprev.getParentElem();
293         }
294       }
295
296       vvar = prev.getStylesheetRoot().getVariableOrParamComposed(m_qname);
297       if (null != vvar)
298       {
299         return vvar;
300       }
301
302     }
303     return null;
304
305   }
306
307 */

308   
309   /**
310    * Tell if this expression returns a stable number that will not change during
311    * iterations within the expression. This is used to determine if a proximity
312    * position predicate can indicate that no more searching has to occur.
313    *
314    *
315    * @return true if the expression represents a stable number.
316    */

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

326   public int getAnalysisBits()
327   {
328     // <<<<<<< TIGER SPECIFIC CHANGE >>>>>>>>>
329
// As we are not supporting Xalan interpretive we are taking away the functionality
330
// dependent on XSLT interpretive Transformer. Only way supported is to use XSLTC
331
// and the execution path needed for supporting standard XPath API defined by
332
// JAXP 1.3 .
333

334     return WalkerFactory.BIT_FILTER;
335   }
336
337
338   /**
339    * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
340    */

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

349   public boolean deepEquals(Expression expr)
350   {
351     if(!isSameClass(expr))
352         return false;
353         
354     if(!m_qname.equals(((Variable)expr).m_qname))
355         return false;
356         
357     // We have to make sure that the qname really references
358
// the same variable element.
359
// <<<<<<< TIGER SPECIFIC CHANGE >>>>>>>>>
360
// As we are not supporting Xalan interpretive we are taking away the functionality
361
// dependent on XSLT interpretive Transformer. Only way supported is to use XSLTC
362
// and the execution path needed for supporting standard XPath API defined by
363
// JAXP 1.3 .
364

365     return true;
366   }
367   
368   static final java.lang.String JavaDoc PSUEDOVARNAMESPACE = "http://xml.apache.org/xalan/psuedovar";
369   
370   /**
371    * Tell if this is a psuedo variable reference, declared by Xalan instead
372    * of by the user.
373    */

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