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 #include "ElemVariable.hpp"
19
20
21
22 #include <xercesc/sax/AttributeList.hpp>
23
24
25
26 #include <xalanc/PlatformSupport/DOMStringHelper.hpp>
27 #include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
28
29
30
31 #include <xalanc/XPath/XObjectFactory.hpp>
32 #include <xalanc/XPath/XPath.hpp>
33
34
35
36 #include "SelectionEvent.hpp"
37 #include "Stylesheet.hpp"
38 #include "StylesheetConstructionContext.hpp"
39 #include "StylesheetExecutionContext.hpp"
40
41
42
43 namespace XALAN_CPP_NAMESPACE {
44
45
46
ElemVariable(StylesheetConstructionContext & constructionContext,Stylesheet & stylesheetTree,const AttributeListType & atts,XalanFileLoc lineNumber,XalanFileLoc columnNumber)47 ElemVariable::ElemVariable(
48 StylesheetConstructionContext& constructionContext,
49 Stylesheet& stylesheetTree,
50 const AttributeListType& atts,
51 XalanFileLoc lineNumber,
52 XalanFileLoc columnNumber) :
53 ParentType(
54 constructionContext,
55 stylesheetTree,
56 lineNumber,
57 columnNumber,
58 StylesheetConstructionContext::ELEMNAME_VARIABLE),
59 m_qname(0),
60 m_selectPattern(0),
61 m_isTopLevel(false),
62 m_value(0),
63 m_varContext(0)
64 {
65 init(constructionContext, stylesheetTree, atts);
66 }
67
68
69
ElemVariable(StylesheetConstructionContext & constructionContext,Stylesheet & stylesheetTree,const AttributeListType & atts,XalanFileLoc lineNumber,XalanFileLoc columnNumber,int xslToken)70 ElemVariable::ElemVariable(
71 StylesheetConstructionContext& constructionContext,
72 Stylesheet& stylesheetTree,
73 const AttributeListType& atts,
74 XalanFileLoc lineNumber,
75 XalanFileLoc columnNumber,
76 int xslToken) :
77 ParentType(
78 constructionContext,
79 stylesheetTree,
80 lineNumber,
81 columnNumber,
82 xslToken),
83 m_qname(0),
84 m_selectPattern(0),
85 m_isTopLevel(false),
86 m_value(0),
87 m_varContext(0)
88 {
89 init(constructionContext, stylesheetTree, atts);
90 }
91
92
93
~ElemVariable()94 ElemVariable::~ElemVariable()
95 {
96 }
97
98
99
100 void
init(StylesheetConstructionContext & constructionContext,Stylesheet & stylesheetTree,const AttributeListType & atts)101 ElemVariable::init(
102 StylesheetConstructionContext& constructionContext,
103 Stylesheet& stylesheetTree,
104 const AttributeListType& atts)
105 {
106 const XalanSize_t nAttrs = atts.getLength();
107
108 for (XalanSize_t i = 0; i < nAttrs; i++)
109 {
110 const XalanDOMChar* const aname = atts.getName(i);
111
112 if (equals(aname, Constants::ATTRNAME_SELECT))
113 {
114 m_selectPattern = constructionContext.createXPath(getLocator(), atts.getValue(i), *this);
115 }
116 else if (equals(aname, Constants::ATTRNAME_NAME))
117 {
118 m_qname = constructionContext.createXalanQName(
119 atts.getValue(i),
120 stylesheetTree.getNamespaces(),
121 getLocator());
122
123 if (m_qname->isValid() == false)
124 {
125 error(
126 constructionContext,
127 XalanMessages::AttributeValueNotValidQName_2Param,
128 Constants::ATTRNAME_NAME.c_str(),
129 atts.getValue(i));
130 }
131 }
132 else if (isAttrOK(
133 aname,
134 atts,
135 i,
136 constructionContext) == false &&
137 processSpaceAttr(
138 Constants::ELEMNAME_VARIABLE_WITH_PREFIX_STRING.c_str(),
139 aname,
140 atts,
141 i,
142 constructionContext) == false)
143 {
144 error(
145 constructionContext,
146 XalanMessages::ElementHasIllegalAttribute_2Param,
147 Constants::ELEMNAME_VARIABLE_WITH_PREFIX_STRING.c_str(),
148 aname);
149 }
150 }
151
152 if (m_qname == 0)
153 {
154 error(
155 constructionContext,
156 XalanMessages::ElementMustHaveAttribute_2Param,
157 Constants::ELEMNAME_VARIABLE_WITH_PREFIX_STRING,
158 Constants::ATTRNAME_NAME);
159 }
160 }
161
162
163
164 const XalanQName&
getNameAttribute() const165 ElemVariable::getNameAttribute() const
166 {
167 assert(m_qname != 0);
168
169 return *m_qname;
170 }
171
172
173
174 void
addToStylesheet(StylesheetConstructionContext & constructionContext,Stylesheet & theStylesheet)175 ElemVariable::addToStylesheet(
176 StylesheetConstructionContext& constructionContext,
177 Stylesheet& theStylesheet)
178 {
179 // Processing a top-level element only...
180 if (&theStylesheet != &getStylesheet())
181 {
182 error(
183 constructionContext,
184 XalanMessages::ElemVariableInstanceAddedToWrongStylesheet);
185 }
186 else if (getParentNodeElem() != 0)
187 {
188 error(
189 constructionContext,
190 XalanMessages::ElemVariableInstanceIsAlreadyParented);
191 }
192 else
193 {
194 theStylesheet.setTopLevelVariable(this);
195
196 m_isTopLevel = true;
197 }
198 }
199
200
201
202 const XalanDOMString&
getElementName() const203 ElemVariable::getElementName() const
204 {
205 return Constants::ELEMNAME_VARIABLE_WITH_PREFIX_STRING;
206 }
207
208
209
210 void
setParentNodeElem(ElemTemplateElement * theParent)211 ElemVariable::setParentNodeElem(ElemTemplateElement* theParent)
212 {
213 if (m_isTopLevel == true)
214 {
215 throw XalanDOMException(XalanDOMException::HIERARCHY_REQUEST_ERR);
216 }
217 else
218 {
219 ParentType::setParentNodeElem(theParent);
220 }
221 }
222
223
224
225 #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
226 const ElemTemplateElement*
startElement(StylesheetExecutionContext & executionContext) const227 ElemVariable::startElement(StylesheetExecutionContext& executionContext) const
228 {
229 assert(m_qname != 0);
230
231 ParentType::startElement(executionContext);
232
233 XObjectPtr theValue;
234
235 if (m_selectPattern == 0)
236 {
237 if (getFirstChildElem() == 0)
238 {
239 theValue = executionContext.getXObjectFactory().createStringReference(s_emptyString);
240 }
241 else
242 {
243 executionContext.beginCreateXResultTreeFrag(executionContext.getCurrentNode());
244 return beginExecuteChildren(executionContext);
245 }
246 }
247 else
248 {
249 theValue = m_selectPattern->execute(*this, executionContext);
250
251 if (0 != executionContext.getTraceListeners())
252 {
253 executionContext.fireSelectEvent(
254 SelectionEvent(
255 executionContext,
256 executionContext.getCurrentNode(),
257 *this,
258 XalanDOMString("select", executionContext.getMemoryManager()),
259 *m_selectPattern,
260 theValue));
261 }
262
263 }
264
265 if (theValue.null() == false)
266 {
267 executionContext.pushVariable(
268 *m_qname,
269 theValue,
270 getParentNodeElem());
271 }
272 else
273 {
274 executionContext.pushVariable(
275 *m_qname,
276 this,
277 getParentNodeElem());
278 }
279
280 return 0;
281 }
282
283
284 void
endElement(StylesheetExecutionContext & executionContext) const285 ElemVariable::endElement(StylesheetExecutionContext& executionContext) const
286 {
287 if (0 == m_selectPattern && 0 != getFirstChildElem())
288 {
289 endExecuteChildren(executionContext);
290
291 executionContext.pushVariable(
292 *m_qname,
293 executionContext.endCreateXResultTreeFrag(),
294 getParentNodeElem());
295 }
296 }
297
298
299
300 #else
301 void
execute(StylesheetExecutionContext & executionContext) const302 ElemVariable::execute(StylesheetExecutionContext& executionContext) const
303 {
304 assert(m_qname != 0);
305
306 ParentType::execute(executionContext);
307
308 const XObjectPtr theValue(getValue(executionContext, executionContext.getCurrentNode()));
309
310 if (theValue.null() == false)
311 {
312 executionContext.pushVariable(
313 *m_qname,
314 theValue,
315 getParentNodeElem());
316 }
317 else
318 {
319 executionContext.pushVariable(
320 *m_qname,
321 this,
322 getParentNodeElem());
323 }
324 }
325 #endif
326
327
328
329 const XPath*
getXPath(XalanSize_t index) const330 ElemVariable::getXPath(XalanSize_t index) const
331 {
332 return index == 0 ? m_selectPattern : 0;
333 }
334
335
336
337 const XObjectPtr
getValue(StylesheetExecutionContext & executionContext,XalanNode * sourceNode) const338 ElemVariable::getValue(
339 StylesheetExecutionContext& executionContext,
340 XalanNode* sourceNode) const
341 {
342 if (m_selectPattern == 0)
343 {
344 if (getFirstChildElem() == 0)
345 {
346 return executionContext.getXObjectFactory().createStringReference(s_emptyString);
347 }
348 else
349 {
350
351 #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
352 executionContext.beginCreateXResultTreeFrag(sourceNode);
353
354 executeChildren(executionContext);
355
356 return executionContext.endCreateXResultTreeFrag();
357 #else
358 return executionContext.createXResultTreeFrag(*this, sourceNode);
359 #endif
360 }
361 }
362 else
363 {
364 XObjectPtr theValue;
365
366 XalanNode* const theCurrentNode = executionContext.getCurrentNode();
367
368 if (theCurrentNode == sourceNode)
369 {
370 theValue = m_selectPattern->execute(*this, executionContext);
371 }
372 else
373 {
374 const XPathExecutionContext::CurrentNodePushAndPop theCurrentNodePushAndPop(executionContext, sourceNode);
375
376 theValue = m_selectPattern->execute(*this, executionContext);
377 }
378
379 if (0 != executionContext.getTraceListeners())
380 {
381 executionContext.fireSelectEvent(
382 SelectionEvent(
383 executionContext,
384 sourceNode,
385 *this,
386 XalanDOMString("select", executionContext.getMemoryManager()),
387 *m_selectPattern,
388 theValue));
389 }
390
391 return theValue;
392 }
393 }
394
395
396
397 }
398