14c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
24c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
34c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * or more contributor license agreements. See the NOTICE file
44c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed with this work for additional information
54c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * regarding copyright ownership. The ASF licenses this file
64c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
74c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * you may not use this file except in compliance with the License.
84c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * You may obtain a copy of the License at
94c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Unless required by applicable law or agreed to in writing, software
134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * See the License for the specific language governing permissions and
164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * limitations under the License.
174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * $Id: XUnresolvedVariable.java 468643 2006-10-28 06:56:03Z minchau $
204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpackage org.apache.xalan.templates;
224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xalan.res.XSLTErrorResources;
244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xalan.transformer.TransformerImpl;
254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.VariableStack;
264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.XPathContext;
274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xpath.objects.XObject;
284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/**
304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * An instance of this class holds unto a variable until
314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * it is executed.  It is used at this time for global
324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * variables which must (we think) forward reference.
334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpublic class XUnresolvedVariable extends XObject
354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson{
364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    static final long serialVersionUID = -256779804767950188L;
374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The node context for execution. */
384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  transient private int m_context;
394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** The transformer context for execution. */
414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  transient private TransformerImpl m_transformer;
424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** An index to the point in the variable stack where we should
444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * begin variable searches for evaluation of expressions.
454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * This is -1 if m_isTopLevel is false.
464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   **/
474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  transient private int m_varStackPos = -1;
484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** An index into the variable stack where the variable context
504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * ends, i.e. at the point we should terminate the search.
514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   **/
524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  transient private int m_varStackContext;
534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** true if this variable or parameter is a global.
554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *  @serial */
564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private boolean m_isGlobal;
574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /** true if this variable or parameter is not currently being evaluated. */
594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  transient private boolean m_doneEval = true;
604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Create an XUnresolvedVariable, that may be executed at a later time.
634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * This is primarily used so that forward referencing works with
644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * global variables.  An XUnresolvedVariable is initially pushed
654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * into the global variable stack, and then replaced with the real
664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * thing when it is accessed.
674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param obj Must be a non-null reference to an ElemVariable.
694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param sourceNode The node context for execution.
704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param transformer The transformer execution context.
714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param varStackPos An index to the point in the variable stack where we should
724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * begin variable searches for evaluation of expressions.
734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param varStackContext An index into the variable stack where the variable context
744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * ends, i.e. at the point we should terminate the search.
754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param isGlobal true if this is a global variable.
764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public XUnresolvedVariable(ElemVariable obj, int sourceNode,
784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                             TransformerImpl transformer,
794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                             int varStackPos, int varStackContext,
804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                             boolean isGlobal)
814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    super(obj);
834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_context = sourceNode;
844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_transformer = transformer;
854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // For globals, this value will have to be updated once we
874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // have determined how many global variables have been pushed.
884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_varStackPos = varStackPos;
894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // For globals, this should zero.
914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_varStackContext = varStackContext;
924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_isGlobal = isGlobal;
944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * For support of literal objects in xpaths.
984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param xctxt The XPath execution context.
1004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return This object.
1024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @throws javax.xml.transform.TransformerException
1044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
1064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    if (!m_doneEval)
1084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      this.m_transformer.getMsgMgr().error
1104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        (xctxt.getSAXLocator(), XSLTErrorResources.ER_REFERENCING_ITSELF,
1114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          new Object[]{((ElemVariable)this.object()).getName().getLocalName()});
1124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    VariableStack vars = xctxt.getVarStack();
1144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // These three statements need to be combined into one operation.
1164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    int currentFrame = vars.getStackFrame();
1174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    //// vars.setStackFrame(m_varStackPos);
1184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    ElemVariable velem = (ElemVariable)m_obj;
1214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    try
1224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_doneEval = false;
1244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if(-1 != velem.m_frameSize)
1254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      	vars.link(velem.m_frameSize);
1264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      XObject var = velem.getValue(m_transformer, m_context);
1274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      m_doneEval = true;
1284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return var;
1294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    finally
1314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // These two statements need to be combined into one operation.
1334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // vars.setStackFrame(currentFrame);
1344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if(-1 != velem.m_frameSize)
1364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson	  	vars.unlink(currentFrame);
1374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set an index to the point in the variable stack where we should
1424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * begin variable searches for evaluation of expressions.
1434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * This is -1 if m_isTopLevel is false.
1444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param top A valid value that specifies where in the variable
1464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * stack the search should begin.
1474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setVarStackPos(int top)
1494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_varStackPos = top;
1514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set an index into the variable stack where the variable context
1554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * ends, i.e. at the point we should terminate the search.
1564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param bottom The point at which the search should terminate, normally
1584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * zero for global variables.
1594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setVarStackContext(int bottom)
1614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_varStackContext = bottom;
1634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Tell what kind of class this is.
1674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return CLASS_UNRESOLVEDVARIABLE
1694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public int getType()
1714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return CLASS_UNRESOLVEDVARIABLE;
1734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Given a request type, return the equivalent string.
1774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * For diagnostic purposes.
1784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return An informational string.
1804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public String getTypeString()
1824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return "XUnresolvedVariable (" + object().getClass().getName() + ")";
1844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson}
188