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 "annotations/annotations.h"
19
20 #include "store/api/item.h"
21 #include "store/api/item_factory.h"
22
23 #include "compiler/expression/expr.h"
24
25 #include "diagnostics/assert.h"
26 #include "diagnostics/util_macros.h"
27
28 #include "system/globalenv.h"
29
30 #include "zorbaserialization/serialize_template_types.h"
31 #include "zorbaserialization/serialize_zorba_types.h"
32
33 namespace zorba {
34
35 SERIALIZABLE_CLASS_VERSIONS(AnnotationInternal)
36
37 SERIALIZABLE_CLASS_VERSIONS(AnnotationList)
38
39
40 std::vector<store::Item_t>
41 AnnotationInternal::theAnnotId2NameMap;
42
43 ItemHandleHashMap<AnnotationInternal::AnnotationId>
44 AnnotationInternal::theAnnotName2IdMap(0, NULL, 64, false);
45
46 std::vector<AnnotationInternal::RuleBitSet>
47 AnnotationInternal::theRuleSet;
48
49
50 /*******************************************************************************
51 Static method, called from GlobalEnvironment::init()
52 ********************************************************************************/
createBuiltIn()53 void AnnotationInternal::createBuiltIn()
54 {
55 store::Item_t qname;
56 AnnotationId id;
57
58 theAnnotId2NameMap.resize(zann_end);
59
60 //
61 // W3C annotations
62 //
63 GENV_ITEMFACTORY->createQName(qname, static_context::W3C_FN_NS, "fn", "public");
64 id = fn_public;
65 theAnnotId2NameMap[id] = qname;
66 theAnnotName2IdMap.insert(qname, id);
67
68 GENV_ITEMFACTORY->createQName(qname, static_context::W3C_FN_NS, "fn", "private");
69 id = fn_private;
70 theAnnotId2NameMap[id] = qname;
71 theAnnotName2IdMap.insert(qname, id);
72
73 #define ZANN(a, b) \
74 GENV_ITEMFACTORY->createQName(qname, ZORBA_ANNOTATIONS_NS, "", #a); \
75 id = zann_##b; \
76 theAnnotId2NameMap[id] = qname; \
77 theAnnotName2IdMap.insert(qname, id);
78
79
80 //
81 // Zorba annotations - deterministic/nondeterministic
82 //
83 ZANN(deterministic, deterministic);
84 ZANN(nondeterministic, nondeterministic);
85
86 //
87 // Zorba annotations - xquery scripting
88 //
89 ZANN(assignable, assignable);
90 ZANN(nonassignable, nonassignable);
91
92 ZANN(sequential, sequential);
93 ZANN(nonsequential, nonsequential);
94
95 //
96 // Zorba annotations - optimizer
97 //
98 ZANN(propagates-input-nodes, propagates_input_nodes);
99 ZANN(must-copy-input-nodes, must_copy_input_nodes);
100
101 //
102 // Zorba annotations - misc
103 //
104 ZANN(variadic, variadic);
105
106 ZANN(streamable, streamable);
107
108 ZANN(cache, cache);
109 ZANN(no-cache, nocache);
110
111 //
112 // Zorba annotations - xqddf
113 //
114 ZANN(unique, unique);
115 ZANN(nonunique, nonunique);
116
117 ZANN(value-equality, value_equality);
118 ZANN(general-equality, general_equality);
119 ZANN(value-range, value_range);
120 ZANN(general-range, general_range);
121
122 ZANN(automatic, automatic);
123 ZANN(manual, manual);
124
125 ZANN(mutable, mutable);
126 ZANN(queue, queue);
127 ZANN(append-only, append_only);
128 ZANN(const, const);
129
130 ZANN(ordered, ordered);
131 ZANN(unordered, unordered);
132
133 ZANN(read-only-nodes, read_only_nodes);
134 ZANN(mutable-nodes, mutable_nodes);
135
136 #undef ZANN
137
138 // create a set of rules to detect conflicts between annotations
139 #define ZANN(a) \
140 ( 1 << static_cast<uint64_t>(AnnotationInternal::a) )
141
142 theRuleSet.push_back(
143 ZANN(zann_unique) |
144 ZANN(zann_nonunique));
145
146 theRuleSet.push_back(
147 ZANN(zann_value_equality) |
148 ZANN(zann_general_equality) |
149 ZANN(zann_value_range) |
150 ZANN(zann_general_range));
151
152 theRuleSet.push_back(
153 ZANN(zann_automatic) |
154 ZANN(zann_manual));
155
156 theRuleSet.push_back(
157 ZANN(zann_mutable) |
158 ZANN(zann_queue) |
159 ZANN(zann_append_only) |
160 ZANN(zann_const));
161
162 theRuleSet.push_back(
163 ZANN(zann_ordered) |
164 ZANN(zann_unordered));
165
166 theRuleSet.push_back(
167 ZANN(zann_assignable) |
168 ZANN(zann_nonassignable));
169
170 theRuleSet.push_back(
171 ZANN(zann_deterministic) |
172 ZANN(zann_nondeterministic));
173
174 theRuleSet.push_back(
175 ZANN(zann_sequential) |
176 ZANN(zann_nonsequential));
177
178 theRuleSet.push_back(
179 ZANN(zann_cache) |
180 ZANN(zann_nocache));
181
182 theRuleSet.push_back(
183 ZANN(fn_private) |
184 ZANN(fn_public));
185
186 theRuleSet.push_back(
187 ZANN(zann_unordered) |
188 ZANN(zann_queue));
189
190 theRuleSet.push_back(
191 ZANN(zann_unordered) |
192 ZANN(zann_append_only));
193
194 theRuleSet.push_back(
195 ZANN(zann_queue) |
196 ZANN(zann_append_only));
197
198 theRuleSet.push_back(
199 ZANN(zann_read_only_nodes) |
200 ZANN(zann_mutable_nodes));
201 #undef ZANN
202 }
203
204
205 /*******************************************************************************
206 Static method, called from GlobalEnvironment::destroy()
207 ********************************************************************************/
destroyBuiltIn()208 void AnnotationInternal::destroyBuiltIn()
209 {
210 theAnnotId2NameMap.clear();
211 theAnnotName2IdMap.clear();
212 }
213
214
215 /*******************************************************************************
216
217 ********************************************************************************/
lookup(const store::Item_t & qname)218 AnnotationInternal::AnnotationId AnnotationInternal::lookup(
219 const store::Item_t& qname)
220 {
221 ItemHandleHashMap<AnnotationId>::iterator ite = theAnnotName2IdMap.find(qname);
222
223 if (ite == theAnnotName2IdMap.end())
224 return zann_end;
225
226 return (*ite).second;
227 }
228
229
230 /*******************************************************************************
231
232 ********************************************************************************/
lookup(AnnotationInternal::AnnotationId id)233 store::Item* AnnotationInternal::lookup(AnnotationInternal::AnnotationId id)
234 {
235 assert(id < zann_end);
236 assert(id < theAnnotId2NameMap.size());
237
238 return theAnnotId2NameMap[id].getp();
239 }
240
241
242 /*******************************************************************************
243
244 ********************************************************************************/
AnnotationInternal(const store::Item_t & qname)245 AnnotationInternal::AnnotationInternal(const store::Item_t& qname)
246 :
247 theId(zann_end),
248 theQName(qname)
249 {
250 ItemHandleHashMap<AnnotationId>::iterator ite = theAnnotName2IdMap.find(qname);
251 if (ite != theAnnotName2IdMap.end())
252 theId = (*ite).second;
253 }
254
255
256 /*******************************************************************************
257
258 ********************************************************************************/
AnnotationInternal(const store::Item_t & qname,std::vector<store::Item_t> & literals)259 AnnotationInternal::AnnotationInternal(
260 const store::Item_t& qname,
261 std::vector<store::Item_t>& literals)
262 :
263 theId(zann_end),
264 theQName(qname)
265 {
266 theLiterals.swap(literals);
267
268 ItemHandleHashMap<AnnotationId>::iterator ite = theAnnotName2IdMap.find(qname);
269 if (ite != theAnnotName2IdMap.end())
270 theId = (*ite).second;
271 }
272
273
274 /*******************************************************************************
275
276 ********************************************************************************/
serialize(::zorba::serialization::Archiver & ar)277 void AnnotationInternal::serialize(::zorba::serialization::Archiver& ar)
278 {
279 SERIALIZE_ENUM(AnnotationId, theId);
280 ar & theQName;
281 ar & theLiterals;
282 }
283
284
285 /*******************************************************************************
286
287 ********************************************************************************/
getQName() const288 const store::Item* AnnotationInternal::getQName() const
289 {
290 return theQName.getp();
291 }
292
293
294 /*******************************************************************************
295
296 ********************************************************************************/
getNumLiterals() const297 csize AnnotationInternal::getNumLiterals() const
298 {
299 return theLiterals.size();
300 }
301
302
303 /*******************************************************************************
304
305 ********************************************************************************/
getLiteral(csize index) const306 store::Item* AnnotationInternal::getLiteral(csize index) const
307 {
308 if (index < theLiterals.size())
309 return theLiterals[index].getp();
310 else
311 return NULL;
312 }
313
314
315 /*******************************************************************************
316
317 ********************************************************************************/
AnnotationList()318 AnnotationList::AnnotationList()
319 {
320 }
321
322
323 /*******************************************************************************
324
325 ********************************************************************************/
~AnnotationList()326 AnnotationList::~AnnotationList()
327 {
328 }
329
330
331 /*******************************************************************************
332
333 ********************************************************************************/
serialize(::zorba::serialization::Archiver & ar)334 void AnnotationList::serialize(::zorba::serialization::Archiver& ar)
335 {
336 ar & theAnnotationList;
337 }
338
339
340 /*******************************************************************************
341
342 ********************************************************************************/
get(csize index) const343 AnnotationInternal* AnnotationList::get(csize index) const
344 {
345 if (index < theAnnotationList.size())
346 return theAnnotationList[index].getp();
347 else
348 return NULL;
349 }
350
351
352 /*******************************************************************************
353
354 ********************************************************************************/
get(AnnotationInternal::AnnotationId id) const355 AnnotationInternal* AnnotationList::get(AnnotationInternal::AnnotationId id) const
356 {
357 for (ListConstIter_t ite = theAnnotationList.begin();
358 ite != theAnnotationList.end();
359 ++ite)
360 {
361 if ((*ite)->getId() == id)
362 return (*ite).getp();
363 }
364
365 return NULL;
366 }
367
368
369 /*******************************************************************************
370
371 ********************************************************************************/
contains(AnnotationInternal::AnnotationId id) const372 bool AnnotationList::contains(AnnotationInternal::AnnotationId id) const
373 {
374 return (get(id) != NULL);
375 }
376
377
378 /*******************************************************************************
379
380 ********************************************************************************/
push_back(const store::Item_t & qname,const std::vector<const_expr * > & literals)381 void AnnotationList::push_back(
382 const store::Item_t& qname,
383 const std::vector<const_expr* >& literals)
384 {
385 std::vector<store::Item_t> lLiterals;
386
387 for (std::vector<const_expr* >::const_iterator it = literals.begin();
388 it != literals.end();
389 ++it)
390 {
391 lLiterals.push_back((*it)->get_val());
392 }
393
394 theAnnotationList.push_back(new AnnotationInternal(qname, lLiterals));
395 }
396
397
398 /*******************************************************************************
399 Called from translator::end_visit(const AnnotationListParsenode& v, void*)
400 ********************************************************************************/
checkConflictingDeclarations(const QueryLoc & loc) const401 void AnnotationList::checkConflictingDeclarations(const QueryLoc& loc) const
402 {
403 // make sure we don't have more annotations then max 64 bit
404 assert(AnnotationInternal::zann_end < 64);
405
406 RuleBitSet lCurrAnn;
407
408 // mark and detect duplicates
409 for (ListConstIter_t ite = theAnnotationList.begin();
410 ite != theAnnotationList.end();
411 ++ite)
412 {
413 const store::Item* qname = (*ite)->getQName();
414 AnnotationId id = (*ite)->getId();
415
416 // detect duplicate annotations (if we "know" them)
417 if (id != AnnotationInternal::zann_end && lCurrAnn.test(id))
418 {
419 RAISE_ERROR(err::XQST0106, loc,
420 ERROR_PARAMS(qname->getStringValue(), ZED(XQST0106_THE_SAME)));
421 }
422
423 lCurrAnn.set(id);
424 }
425
426 // check rules
427 std::vector<RuleBitSet>::const_iterator ite = AnnotationInternal::theRuleSet.begin();
428 std::vector<RuleBitSet>::const_iterator end = AnnotationInternal::theRuleSet.end();
429
430 for (; ite != end; ++ite)
431 {
432 const RuleBitSet& lCurrSet = *ite;
433
434 if ((lCurrAnn & lCurrSet).count() > 1)
435 {
436 // build error string to return set of conflicting annotations
437 std::ostringstream lProblems;
438 for (csize i = 0, j = 0; i < AnnotationInternal::zann_end; ++i)
439 {
440 if (lCurrSet.test(i))
441 {
442 AnnotationId id = static_cast<AnnotationId>(i);
443
444 lProblems << AnnotationInternal::lookup(id)->getStringValue()
445 << ((j == lCurrSet.count() - 1) ? "" : ", ");
446 ++j;
447 }
448 }
449
450 RAISE_ERROR(err::XQST0106, loc,
451 ERROR_PARAMS(lProblems.str(), ZED(XQST0106_CONFLICTING)));
452 }
453 }
454 }
455
456
457 } /* namespace zorba */
458 /* vim:set et sw=2 ts=2: */
459