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