Home | History | Annotate | Download | only in templates
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: XUnresolvedVariable.java 468643 2006-10-28 06:56:03Z minchau $
     20  */
     21 package org.apache.xalan.templates;
     22 
     23 import org.apache.xalan.res.XSLTErrorResources;
     24 import org.apache.xalan.transformer.TransformerImpl;
     25 import org.apache.xpath.VariableStack;
     26 import org.apache.xpath.XPathContext;
     27 import org.apache.xpath.objects.XObject;
     28 
     29 /**
     30  * An instance of this class holds unto a variable until
     31  * it is executed.  It is used at this time for global
     32  * variables which must (we think) forward reference.
     33  */
     34 public class XUnresolvedVariable extends XObject
     35 {
     36     static final long serialVersionUID = -256779804767950188L;
     37   /** The node context for execution. */
     38   transient private int m_context;
     39 
     40   /** The transformer context for execution. */
     41   transient private TransformerImpl m_transformer;
     42 
     43   /** An index to the point in the variable stack where we should
     44    * begin variable searches for evaluation of expressions.
     45    * This is -1 if m_isTopLevel is false.
     46    **/
     47   transient private int m_varStackPos = -1;
     48 
     49   /** An index into the variable stack where the variable context
     50    * ends, i.e. at the point we should terminate the search.
     51    **/
     52   transient private int m_varStackContext;
     53 
     54   /** true if this variable or parameter is a global.
     55    *  @serial */
     56   private boolean m_isGlobal;
     57 
     58   /** true if this variable or parameter is not currently being evaluated. */
     59   transient private boolean m_doneEval = true;
     60 
     61   /**
     62    * Create an XUnresolvedVariable, that may be executed at a later time.
     63    * This is primarily used so that forward referencing works with
     64    * global variables.  An XUnresolvedVariable is initially pushed
     65    * into the global variable stack, and then replaced with the real
     66    * thing when it is accessed.
     67    *
     68    * @param obj Must be a non-null reference to an ElemVariable.
     69    * @param sourceNode The node context for execution.
     70    * @param transformer The transformer execution context.
     71    * @param varStackPos An index to the point in the variable stack where we should
     72    * begin variable searches for evaluation of expressions.
     73    * @param varStackContext An index into the variable stack where the variable context
     74    * ends, i.e. at the point we should terminate the search.
     75    * @param isGlobal true if this is a global variable.
     76    */
     77   public XUnresolvedVariable(ElemVariable obj, int sourceNode,
     78                              TransformerImpl transformer,
     79                              int varStackPos, int varStackContext,
     80                              boolean isGlobal)
     81   {
     82     super(obj);
     83     m_context = sourceNode;
     84     m_transformer = transformer;
     85 
     86     // For globals, this value will have to be updated once we
     87     // have determined how many global variables have been pushed.
     88     m_varStackPos = varStackPos;
     89 
     90     // For globals, this should zero.
     91     m_varStackContext = varStackContext;
     92 
     93     m_isGlobal = isGlobal;
     94   }
     95 
     96   /**
     97    * For support of literal objects in xpaths.
     98    *
     99    * @param xctxt The XPath execution context.
    100    *
    101    * @return This object.
    102    *
    103    * @throws javax.xml.transform.TransformerException
    104    */
    105   public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
    106   {
    107     if (!m_doneEval)
    108     {
    109       this.m_transformer.getMsgMgr().error
    110         (xctxt.getSAXLocator(), XSLTErrorResources.ER_REFERENCING_ITSELF,
    111           new Object[]{((ElemVariable)this.object()).getName().getLocalName()});
    112     }
    113     VariableStack vars = xctxt.getVarStack();
    114 
    115     // These three statements need to be combined into one operation.
    116     int currentFrame = vars.getStackFrame();
    117     //// vars.setStackFrame(m_varStackPos);
    118 
    119 
    120     ElemVariable velem = (ElemVariable)m_obj;
    121     try
    122     {
    123       m_doneEval = false;
    124       if(-1 != velem.m_frameSize)
    125       	vars.link(velem.m_frameSize);
    126       XObject var = velem.getValue(m_transformer, m_context);
    127       m_doneEval = true;
    128       return var;
    129     }
    130     finally
    131     {
    132       // These two statements need to be combined into one operation.
    133       // vars.setStackFrame(currentFrame);
    134 
    135       if(-1 != velem.m_frameSize)
    136 	  	vars.unlink(currentFrame);
    137     }
    138   }
    139 
    140   /**
    141    * Set an index to the point in the variable stack where we should
    142    * begin variable searches for evaluation of expressions.
    143    * This is -1 if m_isTopLevel is false.
    144    *
    145    * @param top A valid value that specifies where in the variable
    146    * stack the search should begin.
    147    */
    148   public void setVarStackPos(int top)
    149   {
    150     m_varStackPos = top;
    151   }
    152 
    153   /**
    154    * Set an index into the variable stack where the variable context
    155    * ends, i.e. at the point we should terminate the search.
    156    *
    157    * @param bottom The point at which the search should terminate, normally
    158    * zero for global variables.
    159    */
    160   public void setVarStackContext(int bottom)
    161   {
    162     m_varStackContext = bottom;
    163   }
    164 
    165   /**
    166    * Tell what kind of class this is.
    167    *
    168    * @return CLASS_UNRESOLVEDVARIABLE
    169    */
    170   public int getType()
    171   {
    172     return CLASS_UNRESOLVEDVARIABLE;
    173   }
    174 
    175   /**
    176    * Given a request type, return the equivalent string.
    177    * For diagnostic purposes.
    178    *
    179    * @return An informational string.
    180    */
    181   public String getTypeString()
    182   {
    183     return "XUnresolvedVariable (" + object().getClass().getName() + ")";
    184   }
    185 
    186 
    187 }
    188