1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "stdafx.h"
17 
18 #include "system/globalenv.h"
19 
20 #include "context/static_context.h"
21 
22 #include "types/typemanager.h"
23 #include "types/casting.h"
24 
25 #include "compiler/api/compilercb.h"
26 
27 #include "runtime/qnames/qnames.h"
28 #include "runtime/visitors/planiter_visitor.h"
29 
30 #include "store/api/store.h"
31 #include "store/api/item_factory.h"
32 #include "store/api/item.h"
33 
34 
35 namespace zorba {
36 #define GENV_GCAST (*GenericCast::instance ())
37 
38 //11.1.1 fn:resolve-QName
39 bool
nextImpl(store::Item_t & result,PlanState & planState) const40 ResolveQNameIterator::nextImpl(store::Item_t& result, PlanState& planState) const
41 {
42   store::Item_t itemQName;
43   store::Item_t itemElem;
44   zstring qname;
45   zstring resNs;
46   zstring resPre;
47   zstring resLocal;
48   zstring::size_type index;
49   store::NsBindings NamespaceBindings;
50   store::NsBindings::const_iterator iter;
51 
52   PlanIteratorState* state;
53   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
54 
55   if (consumeNext(itemQName, theChild0.getp(), planState ))
56   {
57     itemQName->getStringValue2(qname);
58 
59     ascii::trim_whitespace(qname);
60 
61     index = qname.find(":", 0, 1);
62 
63     if (index != zstring::npos)
64     {
65       resPre = qname.substr(0, index);
66       resLocal = qname.substr(index+1, qname.size() - index);
67 
68       // must check for FOCA0002 first
69       if (!GENV_GCAST.castableToNCName(resPre) || ! GENV_GCAST.castableToNCName(resLocal))
70         throw XQUERY_EXCEPTION(
71           err::FOCA0002, ERROR_PARAMS( qname ), ERROR_LOC(loc)
72         );
73     }
74     else
75     {
76       resLocal = qname;
77 
78       if (! GENV_GCAST.castableToNCName(resLocal))
79         throw XQUERY_EXCEPTION(
80           err::FOCA0002, ERROR_PARAMS( qname ), ERROR_LOC(loc)
81         );
82     }
83 
84     if (consumeNext(itemElem, theChild1, planState ))
85     {
86       itemElem->getNamespaceBindings(NamespaceBindings);
87 
88       bool found = false;
89 
90       for (iter = NamespaceBindings.begin();
91            iter != NamespaceBindings.end();
92            ++iter)
93       {
94         if ((*iter).first == resPre)
95         {
96           resNs = (*iter).second;
97           found = true;
98           break;
99         }
100       }
101 
102       if (!found && !resPre.empty())
103         throw XQUERY_EXCEPTION(
104           err::FONS0004, ERROR_PARAMS( resPre ), ERROR_LOC( loc )
105         );
106     }
107 
108     GENV_ITEMFACTORY->createQName(result, resNs, resPre, resLocal);
109 
110     STACK_PUSH(true, state);
111   }
112 
113   STACK_END(state);
114 }
115 
116 
117 //11.1.2 fn:QName
nextImpl(store::Item_t & result,PlanState & planState) const118 bool QNameIterator::nextImpl(store::Item_t& result, PlanState& planState) const
119 {
120   store::Item_t itemURI;
121   store::Item_t itemQName;
122   zstring qname;
123   zstring resNs;
124   zstring resPre;
125   zstring resLocal;
126   zstring::size_type index;
127 
128   PlanIteratorState* state;
129   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
130 
131   if (consumeNext(itemURI, theChild0.getp(), planState ))
132   {
133     itemURI->getStringValue2(resNs);
134 
135     ascii::trim_whitespace(resNs);
136   }
137 
138   consumeNext(itemQName, theChild1.getp(), planState );
139 
140   itemQName->getStringValue2(qname);
141 
142   ascii::trim_whitespace(qname);
143 
144   index = qname.find(":", 0, 1);
145 
146   if (index != zstring::npos)
147   {
148     if (resNs.empty())
149       throw XQUERY_EXCEPTION(
150         err::FOCA0002, ERROR_PARAMS( resNs ), ERROR_LOC(loc)
151       );
152 
153     resPre = qname.substr(0, index);
154     resLocal = qname.substr(index+1, qname.size() - index);
155   }
156   else
157   {
158     resLocal = qname;
159   }
160 
161   if ((index != zstring::npos && ! GENV_GCAST.castableToNCName(resPre)) ||
162       ! GENV_GCAST.castableToNCName(resLocal))
163   {
164     throw XQUERY_EXCEPTION(
165       err::FOCA0002, ERROR_PARAMS( qname ), ERROR_LOC(loc)
166     );
167   }
168 
169   GENV_ITEMFACTORY->createQName(result, resNs, resPre, resLocal);
170 
171   STACK_PUSH(true, state);
172   STACK_END(state);
173 }
174 
175 
176 //11.2.1 op:QName-equal
nextImpl(store::Item_t & result,PlanState & planState) const177 bool QNameEqualIterator::nextImpl(
178     store::Item_t& result,
179     PlanState& planState) const
180 {
181   store::Item_t arg1;
182   store::Item_t arg2;
183 
184   PlanIteratorState* state;
185   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
186 
187   if (consumeNext(arg1, theChild0.getp(), planState ))
188   {
189     if (consumeNext(arg2, theChild1.getp(), planState ))
190     {
191       if(arg1->getLocalName() == arg2->getLocalName())
192       {
193         if (arg1->getNamespace() == arg2->getNamespace())
194           GENV_ITEMFACTORY->createBoolean(result, true);
195         else
196           GENV_ITEMFACTORY->createBoolean(result, false);
197       }
198       else
199       {
200         GENV_ITEMFACTORY->createBoolean(result, false);
201       }
202 
203       STACK_PUSH(true, state );
204     }
205   }
206   STACK_END (state);
207 }
208 
209 
210 //11.2.2 fn:prefix-from-QName
nextImpl(store::Item_t & result,PlanState & planState) const211 bool PrefixFromQNameIterator::nextImpl(
212     store::Item_t& result,
213     PlanState& planState) const
214 {
215   store::Item_t item;
216   zstring tmp;
217 
218   PlanIteratorState* state;
219   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
220 
221   if (consumeNext(item, theChild.getp(), planState))
222   {
223     if(!item->getPrefix().empty())
224     {
225       tmp = item->getPrefix();
226       STACK_PUSH( GENV_ITEMFACTORY->createNCName(result, tmp), state );
227     }
228   }
229   STACK_END (state);
230 }
231 
232 
233 //11.2.3 fn:local-name-from-QName
nextImpl(store::Item_t & result,PlanState & planState) const234 bool LocalNameFromQNameIterator::nextImpl(
235     store::Item_t& result,
236     PlanState& planState) const
237 {
238   store::Item_t item;
239   zstring localName;
240 
241   PlanIteratorState* state;
242   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
243 
244   if (consumeNext(item, theChild.getp(), planState))
245   {
246     localName = item->getLocalName();
247     STACK_PUSH(GENV_ITEMFACTORY->createNCName(result, localName), state);
248   }
249   STACK_END (state);
250 }
251 
252 
253 //11.2.4 fn:namespace-uri-from-QName
nextImpl(store::Item_t & result,PlanState & planState) const254 bool NamespaceUriFromQNameIterator::nextImpl(
255     store::Item_t& result,
256     PlanState& planState) const
257 {
258   store::Item_t item;
259   zstring ns;
260 
261   PlanIteratorState* state;
262   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
263 
264   if (consumeNext(item, theChild.getp(), planState))
265   {
266     ns = item->getNamespace();
267     STACK_PUSH( GENV_ITEMFACTORY->createAnyURI(result, ns), state );
268   }
269   STACK_END (state);
270 }
271 
272 
273 //11.2.5 fn:namespace-uri-for-prefix
nextImpl(store::Item_t & result,PlanState & planState) const274 bool NamespaceUriForPrefixIterator::nextImpl(
275     store::Item_t& result,
276     PlanState& planState) const
277 {
278   store::Item_t itemPrefix, itemElem;
279   zstring resNs;
280   zstring prefix;
281   bool found = false;
282   store::NsBindings NamespaceBindings;
283   store::NsBindings::const_iterator iter;
284 
285   PlanIteratorState* state;
286   DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
287 
288   if (!consumeNext(itemPrefix, theChildren[0].getp(), planState ))
289   {
290     prefix = "";
291   }
292   else
293   {
294     itemPrefix->getStringValue2(prefix);
295     ascii::trim_whitespace(prefix);
296   }
297 
298   if (!consumeNext(itemElem, theChildren[1].getp(), planState ))
299   {
300     ZORBA_ASSERT(false);
301   }
302   else
303   {
304     itemElem->getNamespaceBindings(NamespaceBindings);
305 
306     for (iter = NamespaceBindings.begin();
307          iter != NamespaceBindings.end();
308          ++iter)
309     {
310       if (((*iter).first == prefix) &&
311           !(*iter).second.empty())
312         {
313           resNs = (*iter).second;
314           found = true;
315           break;
316         }
317     }
318   }
319 
320   if (found)
321   {
322     STACK_PUSH( GENV_ITEMFACTORY->createString(result, resNs), state );
323   }
324 
325   STACK_END (state);
326 }
327 
328 //11.2.6 fn:in-scope-prefixes
init(PlanState & planState)329 void InScopePrefixesIteratorState::init(PlanState& planState)
330 {
331   PlanIteratorState::init(planState);
332   theBindings.clear();
333   theCurrentPos = 0;
334 }
335 
reset(PlanState & planState)336 void InScopePrefixesIteratorState::reset(PlanState& planState)
337 {
338   PlanIteratorState::reset(planState);
339   theBindings.clear();
340   theCurrentPos = 0;
341 }
342 
343 bool
nextImpl(store::Item_t & result,PlanState & planState) const344 InScopePrefixesIterator::nextImpl(store::Item_t& result, PlanState& planState) const
345 {
346   store::Item_t itemElem;
347   zstring ncname("xml");
348 
349   InScopePrefixesIteratorState* state;
350   DEFAULT_STACK_INIT(InScopePrefixesIteratorState, state, planState);
351 
352   STACK_PUSH(GENV_ITEMFACTORY->createNCName(result, ncname), state);
353 
354   if (consumeNext(itemElem, theChild.getp(), planState ))
355   {
356     itemElem->getNamespaceBindings(state->theBindings);
357     while (state->theCurrentPos < state->theBindings.size())
358     {
359       if (!state->theBindings[state->theCurrentPos].second.empty())
360       {
361         ncname = state->theBindings[state->theCurrentPos].first;
362         STACK_PUSH(GENV_ITEMFACTORY->createNCName(result, ncname), state);
363       }
364       state->theCurrentPos++;
365     }
366   }
367 
368   STACK_END (state);
369 }
370 
371 } // namespace zorba
372 /* vim:set et sw=2 ts=2: */
373