001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: XUnresolvedVariable.java 468643 2006-10-28 06:56:03Z minchau $
020 */
021 package org.apache.xalan.templates;
022
023 import org.apache.xalan.res.XSLTErrorResources;
024 import org.apache.xalan.transformer.TransformerImpl;
025 import org.apache.xpath.VariableStack;
026 import org.apache.xpath.XPathContext;
027 import org.apache.xpath.objects.XObject;
028
029 /**
030 * An instance of this class holds unto a variable until
031 * it is executed. It is used at this time for global
032 * variables which must (we think) forward reference.
033 */
034 public class XUnresolvedVariable extends XObject
035 {
036 static final long serialVersionUID = -256779804767950188L;
037 /** The node context for execution. */
038 transient private int m_context;
039
040 /** The transformer context for execution. */
041 transient private TransformerImpl m_transformer;
042
043 /** An index to the point in the variable stack where we should
044 * begin variable searches for evaluation of expressions.
045 * This is -1 if m_isTopLevel is false.
046 **/
047 transient private int m_varStackPos = -1;
048
049 /** An index into the variable stack where the variable context
050 * ends, i.e. at the point we should terminate the search.
051 **/
052 transient private int m_varStackContext;
053
054 /** true if this variable or parameter is a global.
055 * @serial */
056 private boolean m_isGlobal;
057
058 /** true if this variable or parameter is not currently being evaluated. */
059 transient private boolean m_doneEval = true;
060
061 /**
062 * Create an XUnresolvedVariable, that may be executed at a later time.
063 * This is primarily used so that forward referencing works with
064 * global variables. An XUnresolvedVariable is initially pushed
065 * into the global variable stack, and then replaced with the real
066 * thing when it is accessed.
067 *
068 * @param obj Must be a non-null reference to an ElemVariable.
069 * @param sourceNode The node context for execution.
070 * @param transformer The transformer execution context.
071 * @param varStackPos An index to the point in the variable stack where we should
072 * begin variable searches for evaluation of expressions.
073 * @param varStackContext An index into the variable stack where the variable context
074 * ends, i.e. at the point we should terminate the search.
075 * @param isGlobal true if this is a global variable.
076 */
077 public XUnresolvedVariable(ElemVariable obj, int sourceNode,
078 TransformerImpl transformer,
079 int varStackPos, int varStackContext,
080 boolean isGlobal)
081 {
082 super(obj);
083 m_context = sourceNode;
084 m_transformer = transformer;
085
086 // For globals, this value will have to be updated once we
087 // have determined how many global variables have been pushed.
088 m_varStackPos = varStackPos;
089
090 // For globals, this should zero.
091 m_varStackContext = varStackContext;
092
093 m_isGlobal = isGlobal;
094 }
095
096 /**
097 * For support of literal objects in xpaths.
098 *
099 * @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 }