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 "validate.h"
19
20 #include "diagnostics/xquery_diagnostics.h"
21
22 #include "system/globalenv.h"
23
24 #include "types/casting.h"
25 #include "types/typeops.h"
26
27 #ifndef ZORBA_NO_XMLSCHEMA
28
29 #include "types/schema/schema.h"
30 #include "types/schema/SchemaValidatorFilter.h"
31 #include "types/schema/EventSchemaValidator.h"
32 #include "types/schema/StrX.h"
33 #include "types/schema/revalidateUtils.h"
34
35 #include "zorbatypes/duration.h"
36 #include "zorbatypes/datetime.h"
37
38 #endif
39
40 #include "api/unmarshaller.h"
41
42 #include "compiler/parser/query_loc.h"
43
44 #include "store/api/copymode.h"
45 #include "store/api/item.h"
46 #include "store/api/item_factory.h"
47 #include "store/api/iterator.h"
48 #include "store/api/store.h"
49
50 #include "context/dynamic_context.h"
51 #include "context/static_context.h"
52 #include "context/namespace_context.h"
53
54 #include "diagnostics/assert.h"
55 #include "zorba/store_consts.h"
56
57 //using namespace std;
58
59 namespace zorba
60 {
61
62
effectiveValidationValue(store::Item_t & result,const store::Item_t & sourceNode,const store::Item_t & typeName,TypeManager * typeManager,ParseConstants::validation_mode_t validationMode,const static_context * sctx,const QueryLoc & loc)63 bool Validator::effectiveValidationValue(
64 store::Item_t& result,
65 const store::Item_t& sourceNode,
66 const store::Item_t& typeName,
67 TypeManager* typeManager,
68 ParseConstants::validation_mode_t validationMode,
69 const static_context* sctx,
70 const QueryLoc& loc)
71 {
72 //cout << "Starting Validation typeManager: " << typeManager <<
73 //endl; cout.flush();
74 try
75 {
76 return realValidationValue(result, sourceNode, typeName,
77 typeManager, validationMode, sctx, loc);
78 }
79 catch (ZorbaException& e)
80 {
81 set_source( e, loc );
82
83 if ( sourceNode->isNode() &&
84 sourceNode->getNodeKind() == store::StoreConsts::documentNode )
85 {
86 zstring baseUri;
87 sourceNode->getDocumentURI(baseUri);
88
89 //e.theDescription += " while validating document '" + baseUri + "'";
90 }
91 throw;
92 }
93 }
94
95
realValidationValue(store::Item_t & result,const store::Item_t & sourceNode,const store::Item_t & typeName,TypeManager * typeManager,ParseConstants::validation_mode_t validationMode,const static_context * sctx,const QueryLoc & loc)96 bool Validator::realValidationValue(
97 store::Item_t& result,
98 const store::Item_t& sourceNode,
99 const store::Item_t& typeName,
100 TypeManager* typeManager,
101 ParseConstants::validation_mode_t validationMode,
102 const static_context* sctx,
103 const QueryLoc& loc)
104 {
105 xqtref_t type;
106
107 if (!sourceNode->isNode() ||
108 !(sourceNode->getNodeKind()==store::StoreConsts::documentNode ||
109 sourceNode->getNodeKind()==store::StoreConsts::elementNode
110 ) )
111 {
112 throw XQUERY_EXCEPTION( err::XQTY0030, ERROR_LOC( loc ) );
113 }
114
115 // verify number of child elements when source is a document node
116 if (sourceNode->getNodeKind() == store::StoreConsts::documentNode)
117 {
118 //don't allow more than one child element in documents
119 store::Iterator_t child_it;
120 child_it = sourceNode->getChildren();
121 store::Item_t child;
122 int nr_child_elements = 0;
123 while ( child_it->next(child) )
124 {
125 if ( child->isNode() &&
126 child->getNodeKind() == store::StoreConsts::elementNode)
127 {
128 if (nr_child_elements)
129 {
130 throw XQUERY_EXCEPTION(
131 err::XQDY0061,
132 ERROR_PARAMS( ZED( DocNodeMultipleElements ) ),
133 ERROR_LOC( loc )
134 );
135 }
136 nr_child_elements++;
137 }
138 }
139 }
140
141 Schema* schema = typeManager->getSchema();
142
143 if ( !schema )
144 {
145 //cout << "No schema: isNode() " << sourceNode->isNode() << " nodeKind: "<<
146 // sourceNode->getNodeKind() << endl;
147
148 if ( validationMode == ParseConstants::val_dtd_lax)
149 {
150 // when dtd validation enabled avoid using schema object
151 result = sourceNode;
152 return true;
153 }
154 else
155 {
156 // if we got here it basicaly means that there was no import but
157 // validation is used so we need to set up schema in the typeManager anyway
158 // validation has to work for xsiType and built-in types
159
160 TypeManagerImpl *typeManagerImpl = static_cast<TypeManagerImpl*>(typeManager);
161 typeManagerImpl->initializeSchema();
162 schema = typeManager->getSchema();
163 }
164 }
165
166 #ifndef ZORBA_NO_XMLSCHEMA
167
168 EventSchemaValidator schemaValidator =
169 EventSchemaValidator(typeManager,
170 schema->getGrammarPool(),
171 validationMode == ParseConstants::val_lax,
172 loc);
173
174 switch (sourceNode->getNodeKind())
175 {
176 case store::StoreConsts::documentNode:
177 {
178 //cout << "Validate document" << "\n"; cout.flush();
179
180 if ( validationMode == ParseConstants::val_typename )
181 {
182 //cout << "Validate type: " << typeName->getLocalName()
183 // << " @ " << typeName->getNamespace() << "\n"; cout.flush();
184 schemaValidator.startType(typeName);
185 }
186 else
187 {
188 schemaValidator.startDoc();
189
190 // ask for the type of the root element to populate
191 // the cache with anonymous types
192 store::Iterator_t children = sourceNode->getChildren();
193 store::Item_t child;
194 while ( children->next(child) )
195 {
196 if ( child->isNode() &&
197 child->getNodeKind()==store::StoreConsts::elementNode )
198 {
199 typeManager->getSchema()->
200 createXQTypeFromElementName(typeManager,
201 child->getNodeName(),
202 false,
203 loc);
204 break;
205 }
206 }
207 }
208
209 zstring docBaseUri;
210 zstring docUri;
211 sourceNode->getBaseURI(docBaseUri);
212 sourceNode->getDocumentURI(docUri);
213
214 store::Item_t newDoc;
215 GENV_ITEMFACTORY->createDocumentNode(newDoc, docBaseUri, docUri);
216
217 processChildren(sctx,
218 typeManager,
219 schemaValidator,
220 newDoc,
221 sourceNode->getChildren(),
222 loc);
223
224 if ( validationMode == ParseConstants::val_typename )
225 {
226 schemaValidator.endType();
227 //cout << "End Validate type: " << typeName->getLocalName()
228 // << " @ " << typeName->getNamespace() << "\n";
229 //cout.flush();
230 }
231 else
232 {
233 schemaValidator.endDoc();
234 }
235
236 //cout << "End Validate doc" << "\n"; cout.flush();
237
238 result = newDoc;
239 result->markValidated();
240 return true;
241 }
242 case store::StoreConsts::elementNode:
243 {
244 if ( validationMode == ParseConstants::val_typename )
245 {
246 //cout << "Validate type: " << typeName->getLocalName() <<" @ "
247 // << typeName->getNamespace() << "\n"; cout.flush();
248
249 schemaValidator.startType(typeName);
250 }
251 else
252 {
253 //cout << "Validate element" << "\n"; cout.flush();
254 schemaValidator.startDoc();
255
256 // ask for the type of the root element to populate the cache
257 // with anonymous types
258 typeManager->getSchema()->
259 createXQTypeFromElementName(typeManager,
260 sourceNode->getNodeName(),
261 false,
262 loc);
263 }
264
265 store::Item_t newElem = processElement(sctx,
266 typeManager,
267 schemaValidator,
268 NULL,
269 sourceNode,
270 loc);
271
272 if ( validationMode == ParseConstants::val_typename )
273 {
274 schemaValidator.endType();
275 //cout << "End Validate type: " << typeName->getLocalName()
276 // <<" @ "<< typeName->getNamespace() << "\n";cout.flush();
277 }
278 else
279 {
280 schemaValidator.endDoc();
281 //cout << "End Validate elem" << "\n"; cout.flush();
282 }
283
284 result = newElem;
285 result->markValidated();
286 return true;
287 }
288 default:
289 {
290 throw XQUERY_EXCEPTION( err::XQTY0030, ERROR_LOC( loc ) );
291 }
292 }
293 #endif // ZORBA_NO_XMLSCHEMA
294 }
295
296
297 #ifndef ZORBA_NO_XMLSCHEMA
298
299
processElement(const static_context * sctx,TypeManager * typeManager,EventSchemaValidator & schemaValidator,store::Item * parent,const store::Item_t & element,const QueryLoc & loc)300 store::Item_t Validator::processElement(
301 const static_context* sctx,
302 TypeManager* typeManager,
303 EventSchemaValidator& schemaValidator,
304 store::Item* parent,
305 const store::Item_t& element,
306 const QueryLoc& loc)
307 {
308 ZORBA_ASSERT(element->isNode());
309 ZORBA_ASSERT(element->getNodeKind() == store::StoreConsts::elementNode);
310
311
312 store::Item_t nodeName = element->getNodeName();
313 zstring baseUri;
314 element->getBaseURI(baseUri);
315
316 schemaValidator.startElem(nodeName);
317
318 // namespace declarations must go first
319 processNamespaces( schemaValidator, element);
320
321 // since the type of an element is determined only after the validator
322 // receives all of it's attributes, and an attribute node needs it's parent
323 // when created we need to go through the attributes twice: once for
324 // validation and once for creation
325 validateAttributes(schemaValidator, element->getAttributes());
326
327 // not required since getTypeQName will trigger processElement in validator
328 //schemaValidator.endAttrs();
329
330 store::Item_t typeName = schemaValidator.getTypeQName();
331
332 bool isSubstitutionGroup = false;
333 if ( schemaValidator.getSubstitutedElemQName() )
334 isSubstitutionGroup = true;
335
336 store::Item_t newElem;
337
338 store::NsBindings bindings;
339 element->getNamespaceBindings(bindings);
340
341 bool haveTypedValue = true;
342 bool haveEmptyValue = false;
343
344 if ( typeName!=NULL && typeManager!=NULL )
345 {
346 xqtref_t schemaType = typeManager->create_named_type(typeName,
347 TypeConstants::QUANT_ONE,
348 loc);
349
350 if ( schemaType!=NULL )
351 {
352 haveTypedValue = typeHasValue(schemaType);
353 haveEmptyValue = typeHasEmptyValue(schemaType);
354 }
355 }
356
357 store::Item_t elemName = element->getNodeName();
358 GENV_ITEMFACTORY->createElementNode(newElem, parent, elemName,
359 typeName, haveTypedValue, haveEmptyValue,
360 bindings, baseUri, isSubstitutionGroup);
361
362 processAttributes(sctx,
363 typeManager,
364 schemaValidator,
365 (store::Item *)newElem,
366 element->getAttributes(),
367 loc);
368
369 processChildren(sctx,
370 typeManager,
371 schemaValidator,
372 (store::Item *)newElem,
373 element->getChildren(),
374 loc);
375
376 schemaValidator.endElem(nodeName);
377
378 return newElem;
379 }
380
381
validateAttributes(EventSchemaValidator & schemaValidator,store::Iterator_t attributes)382 void Validator::validateAttributes(
383 EventSchemaValidator& schemaValidator,
384 store::Iterator_t attributes)
385 {
386 store::Item_t attribute;
387
388 while ( attributes->next(attribute) )
389 {
390 ZORBA_ASSERT(attribute->isNode());
391 ZORBA_ASSERT(attribute->getNodeKind() == store::StoreConsts::attributeNode);
392
393 //cout << " v - attr: " << attribute->getNodeName()->getLocalName() << ":" <<
394 // attribute->getStringValue() << "\n"; cout.flush();
395
396 store::Item_t attName = attribute->getNodeName();
397 schemaValidator.attr(attName, attribute->getStringValue());
398 }
399 }
400
401
processAttributes(const static_context * sctx,TypeManager * typeManager,EventSchemaValidator & schemaValidator,store::Item * parent,store::Iterator_t attributes,const QueryLoc & loc)402 void Validator::processAttributes(
403 const static_context* sctx,
404 TypeManager* typeManager,
405 EventSchemaValidator& schemaValidator,
406 store::Item* parent,
407 store::Iterator_t attributes,
408 const QueryLoc& loc)
409 {
410 std::list<AttributeValidationInfo*>* attList =
411 schemaValidator.getAttributeList();
412 std::list<AttributeValidationInfo*>::iterator curAtt;
413
414 for( curAtt = attList->begin(); curAtt != attList->end(); ++curAtt )
415 {
416 AttributeValidationInfo* att = *curAtt;
417 //cout << " v proccessATT2: " << att->theLocalName << " T: " <<
418 // att->theTypeName << "\n";
419
420 store::Item_t attQName;
421 GENV_ITEMFACTORY->createQName(attQName,
422 att->theUri,
423 att->thePrefix,
424 att->theLocalName);
425
426 zstring typePrefix;
427
428 // hack around typeManager bug for comparing QNames
429 if (att->theTypeURI == Schema::XSD_NAMESPACE)
430 typePrefix = "xs";
431 else
432 typePrefix = "";
433
434 store::Item_t typeQName;
435 GENV_ITEMFACTORY->createQName(typeQName,
436 att->theTypeURI,
437 typePrefix,
438 att->theTypeName);
439
440 store::NsBindings bindings;
441 parent->getNamespaceBindings(bindings);
442
443 std::vector<store::Item_t> typedValues;
444 processTextValue(sctx,
445 typeManager,
446 bindings,
447 typeQName,
448 att->theValue,
449 typedValues,
450 loc);
451
452 store::Item_t validatedAttNode;
453 if ( typedValues.size()==1 ) // hack around serialization bug
454 GENV_ITEMFACTORY->createAttributeNode(validatedAttNode,
455 parent,
456 attQName,
457 typeQName,
458 typedValues[0]);
459 else
460 GENV_ITEMFACTORY->createAttributeNode(validatedAttNode,
461 parent,
462 attQName,
463 typeQName,
464 typedValues);
465 }
466 }
467
468
processChildren(const static_context * sctx,TypeManager * typeManager,EventSchemaValidator & schemaValidator,store::Item * parent,store::Iterator_t children,const QueryLoc & loc)469 void Validator::processChildren(
470 const static_context* sctx,
471 TypeManager* typeManager,
472 EventSchemaValidator& schemaValidator,
473 store::Item* parent,
474 store::Iterator_t children,
475 const QueryLoc& loc)
476 {
477 store::Item_t child;
478 bool inTextContent = false;
479 bool hasChildrenElements = false;
480 zstring textNodeValue = zstring("");
481 std::vector<store::Item*> textContent;
482
483 while ( children->next(child) )
484 {
485 if ( child->isNode() )
486 {
487 //cout << " > child: " << (long)child->getNodeKind() << " " <<
488 // //(child->getType() != NULL ? child->getType()->getLocalName() : "type_NULL" ) <<
489 // "\n"; cout.flush();
490
491 switch ( child->getNodeKind() )
492 {
493 case store::StoreConsts::elementNode:
494 if (inTextContent)
495 {
496 hasChildrenElements = true;
497 processTextContent(sctx, typeManager, schemaValidator, parent,
498 hasChildrenElements, textNodeValue, textContent, loc);
499 textNodeValue = "";
500 inTextContent = false;
501 textContent.clear();
502 }
503 processElement(sctx, typeManager, schemaValidator, parent, child, loc);
504 break;
505
506 case store::StoreConsts::attributeNode:
507 ZORBA_ASSERT(false);
508 break;
509
510 case store::StoreConsts::documentNode:
511 ZORBA_ASSERT(false);
512 break;
513
514 case store::StoreConsts::textNode:
515 {
516 // keep on adding the text
517 inTextContent = true;
518 zstring childStringValue;
519 child->getStringValue2(childStringValue);
520 textNodeValue += childStringValue;
521 textContent.push_back(child.getp());
522 }
523 break;
524
525 case store::StoreConsts::piNode:
526 {
527 //cout << " - pi: " << child->getStringValue() << "\n";cout.flush();
528 if ( inTextContent )
529 {
530 textContent.push_back(child.getp());
531 }
532 else
533 {
534 store::Item_t piNode;
535 zstring piTarget =child->getTarget();
536 zstring childStringValue;
537 child->getStringValue2(childStringValue);
538 zstring childBaseUri;
539 child->getBaseURI(childBaseUri);
540
541 GENV_ITEMFACTORY->createPiNode(piNode, parent, piTarget,
542 childStringValue, childBaseUri);
543 }
544 }
545 break;
546
547 case store::StoreConsts::commentNode:
548 {
549 //cout << " - comment: " << child->getStringValue() <<
550 // "\n"; cout.flush();
551 if ( inTextContent )
552 {
553 textContent.push_back(child.getp());
554 }
555 else
556 {
557 store::Item_t commentNode;
558 zstring childStringValue;
559 child->getStringValue2(childStringValue);
560 GENV_ITEMFACTORY->createCommentNode(commentNode, parent, childStringValue);
561 }
562 }
563 break;
564
565 case store::StoreConsts::anyNode:
566 //cout << " - any: " << child->getStringValue() <<"\n";cout.flush();
567 ZORBA_ASSERT(false);
568 break;
569
570 default:
571 ZORBA_ASSERT(false);
572 }
573 }
574 }
575
576 if (inTextContent)
577 {
578 processTextContent(sctx, typeManager, schemaValidator, parent,
579 hasChildrenElements, textNodeValue, textContent, loc);
580 textNodeValue = "";
581 inTextContent = false;
582 }
583 }
584
processTextContent(const static_context * sctx,TypeManager * typeManager,EventSchemaValidator & schemaValidator,store::Item * parent,bool hasChildrenElements,zstring & textNodeValue,std::vector<store::Item * > & textContent,const QueryLoc & loc)585 void Validator::processTextContent(
586 const static_context* sctx,
587 TypeManager* typeManager,
588 EventSchemaValidator& schemaValidator,
589 store::Item* parent,
590 bool hasChildrenElements,
591 zstring& textNodeValue,
592 std::vector<store::Item*>& textContent,
593 const QueryLoc& loc)
594 {
595 for ( std::size_t i = 0; i<textContent.size(); i++)
596 {
597 store::Item* child = textContent[i];
598 switch ( child->getNodeKind() )
599 {
600 case store::StoreConsts::textNode:
601 {
602 if (hasChildrenElements)
603 {
604 zstring childStringValue;
605 child->getStringValue2(childStringValue);
606 finishTextNode(sctx, typeManager, schemaValidator, parent,
607 childStringValue, loc);
608 }
609 }
610 break;
611
612 case store::StoreConsts::piNode:
613 {
614 store::Item_t piNode;
615 zstring piTarget =child->getTarget();
616 zstring childStringValue;
617 child->getStringValue2(childStringValue);
618 zstring childBaseUri;
619 child->getBaseURI(childBaseUri);
620
621 GENV_ITEMFACTORY->createPiNode(piNode, parent, piTarget,
622 childStringValue, childBaseUri);
623 }
624 break;
625
626 case store::StoreConsts::commentNode:
627 {
628 store::Item_t commentNode;
629 zstring childStringValue;
630 child->getStringValue2(childStringValue);
631 GENV_ITEMFACTORY->createCommentNode(commentNode, parent, childStringValue);
632 }
633 break;
634
635 case store::StoreConsts::elementNode:
636 case store::StoreConsts::attributeNode:
637 case store::StoreConsts::documentNode:
638 case store::StoreConsts::anyNode:
639 //cout << " - any: " << child->getStringValue() <<"\n";cout.flush();
640 ZORBA_ASSERT(false);
641 break;
642
643 default:
644 ZORBA_ASSERT(false);
645 }
646 }
647
648 if (!hasChildrenElements)
649 {
650 finishTextNode(sctx, typeManager, schemaValidator, parent,
651 textNodeValue, loc);
652 }
653 }
654
finishTextNode(const static_context * sctx,TypeManager * typeManager,EventSchemaValidator & schemaValidator,store::Item * parent,zstring & textNodeValue,const QueryLoc & loc)655 void Validator::finishTextNode(
656 const static_context* sctx,
657 TypeManager* typeManager,
658 EventSchemaValidator& schemaValidator,
659 store::Item* parent,
660 zstring& textNodeValue,
661 const QueryLoc& loc)
662 {
663 schemaValidator.text(textNodeValue);
664
665 store::Item_t typeQName = schemaValidator.getTypeQName();
666
667 store::Item_t validatedTextNode;
668
669 TypeIdentifier_t typeIdentifier =
670 TypeIdentifier::createNamedType(
671 Unmarshaller::newString( typeQName->getNamespace() ),
672 Unmarshaller::newString( typeQName->getLocalName() )
673 );
674
675 //xqType is NULL, create_type can't find it
676 xqtref_t xqType = typeManager->create_type(*typeIdentifier);
677
678 #if 0 // enable this to debug children values
679 if ( typeQName.getp() && xqType.getp() )
680 {
681 cout << " - text: '" << textNodeValue << "' T: " <<
682 typeQName->getLocalName() << "\n"; cout.flush();
683 cout << " xqT: " << xqType->toString() << " content_kind: " <<
684 (long)xqType->content_kind() << " tKind:" << (long)xqType->type_kind() << " \n";
685 cout.flush();
686 }
687 else
688 cout << " - text2: '" << textNodeValue << "' tQN: " <<
689 (typeQName ? typeQName->getStringValue() : "NULL") <<
690 " xqT:" << ( xqType.getp() ? xqType.getp()->toString() : "NULL" )
691 << "\n"; cout.flush();
692 #endif
693
694 if ( xqType != NULL &&
695 xqType->content_kind() == XQType::SIMPLE_CONTENT_KIND )
696 {
697 store::NsBindings nsBindings;
698 parent->getNamespaceBindings(nsBindings);
699 std::vector<store::Item_t> typedValues;
700
701 processTextValue(sctx,
702 typeManager,
703 nsBindings,
704 typeQName,
705 textNodeValue,
706 typedValues,
707 loc);
708
709 if ( typedValues.size() == 1 ) // hack around serialization bug
710 GENV_ITEMFACTORY->createTextNode(validatedTextNode, parent,
711 typedValues[0]);
712 else
713 GENV_ITEMFACTORY->createTextNode(validatedTextNode, parent,
714 typedValues);
715 }
716 else if ( xqType!=NULL &&
717 (xqType->content_kind()==XQType::ELEMENT_ONLY_CONTENT_KIND ||
718 xqType->content_kind()==XQType::EMPTY_CONTENT_KIND ))
719 {
720 // if text not valid the schemaValidator should have already
721 // thrown an error
722
723 // XQ XP Datamodel Spec: http://www.w3.org/TR/xpath-datamodel/
724 // section 6.7.4 Construction from a PSVI
725 if ( !utf8::is_whitespace(textNodeValue) )
726 {
727 zstring empty;
728 GENV_ITEMFACTORY->createTextNode(validatedTextNode,
729 parent,
730 empty);
731 //cout << " -- create empty text : ElementOnly || Empty" << endl;
732 }
733 else
734 {
735 //cout << " -- skip this text: (ElemOnly || Empty) && whitespace" << endl;
736 }
737 }
738 else
739 //if ( xqType!=NULL &&
740 // xqType->content_kind()==XQType::MIXED_CONTENT_KIND )
741 {
742 // if text not valid the schemaValidator should have already
743 // thrown an error
744 GENV_ITEMFACTORY->createTextNode(validatedTextNode,
745 parent,
746 textNodeValue);
747 //cout << " -- create empty text: Mixed" << endl;
748 }
749 }
750
751
752
processNamespaces(EventSchemaValidator & schemaValidator,const store::Item_t & item)753 void Validator::processNamespaces (
754 EventSchemaValidator& schemaValidator,
755 const store::Item_t& item)
756 {
757 store::NsBindings bindings;
758 item->getNamespaceBindings(bindings,
759 store::StoreConsts::ONLY_LOCAL_NAMESPACES);
760
761 for (unsigned long i = 0; i < bindings.size(); i++)
762 {
763 schemaValidator.ns(bindings[i].first, bindings[i].second);
764 }
765 }
766
767
processTextValue(const static_context * sctx,TypeManager * typeManager,store::NsBindings & bindings,const store::Item_t & typeQName,zstring & textValue,std::vector<store::Item_t> & resultList,const QueryLoc & loc)768 void Validator::processTextValue(
769 const static_context* sctx,
770 TypeManager* typeManager,
771 store::NsBindings& bindings,
772 const store::Item_t& typeQName,
773 zstring& textValue,
774 std::vector<store::Item_t>& resultList,
775 const QueryLoc& loc)
776 {
777 xqtref_t type = typeManager->create_named_type(typeQName.getp(),
778 TypeConstants::QUANT_ONE,
779 loc);
780
781 //cout << " - processTextValue: " << typeQName->getPrefix()
782 // << ":" << typeQName->getLocalName() << "@"
783 // << typeQName->getNamespace() ; cout.flush();
784 //cout << " type: " << (type==NULL ? "NULL" : type->toString()) << "\n"; cout.flush();
785
786 // TODO: we probably need the ns bindings from the static context
787 // surrounding the original validate_expr, not planState.sctx()
788 namespace_context nsCtx = namespace_context(sctx, bindings);
789
790 store::Item_t result;
791 if (type != NULL)
792 {
793 if ( type->type_kind() == XQType::USER_DEFINED_KIND )
794 {
795 const UserDefinedXQType udt = static_cast<const UserDefinedXQType&>(*type);
796
797 if ( udt.isList() || udt.isUnion() )
798 {
799 typeManager->getSchema()->parseUserSimpleTypes(textValue, type, resultList, loc);
800 }
801 else if (udt.isAtomic())
802 {
803 bool res = typeManager->getSchema()->
804 parseUserAtomicTypes(textValue, type.getp(), result, &nsCtx, loc);
805
806 ZORBA_ASSERT(res);
807 resultList.push_back(result);
808 }
809 else if (udt.isComplex() &&
810 udt.content_kind() == XQType::SIMPLE_CONTENT_KIND)
811 {
812 try
813 {
814 // if complex type with simple content parse text by the base
815 // type which has to be simple
816 xqtref_t baseType = udt.getBaseType();
817
818 while ( baseType->type_kind() == XQType::USER_DEFINED_KIND &&
819 static_cast<const UserDefinedXQType&>(*baseType).isComplex() )
820 {
821 const UserDefinedXQType udBaseType = static_cast<const UserDefinedXQType&>(*baseType);
822 baseType = udBaseType.getBaseType();
823 }
824 bool res = GenericCast::castToSimple(textValue, baseType.getp(),
825 resultList, typeManager, loc);
826
827 // if this assert fails it means the validator and zorba casting code
828 // don't follow the same rules
829 ZORBA_ASSERT(res);
830 }
831 catch(ZorbaException const& /*err*/)
832 {
833 // do nothing here, the validator will throw the right error at end
834 // elemet event call
835 //std::cout << "validate.cpp: processTextValue1 '" << textValue << "' err:" << err.toString() << std::endl; std::cout.flush();
836 }
837 }
838 }
839 else if (type->type_kind() == XQType::ATOMIC_TYPE_KIND)
840 {
841 try
842 {
843 bool res = GenericCast::castToAtomic(result, textValue, type.getp(),
844 typeManager, &nsCtx, loc);
845 ZORBA_ASSERT(res);
846 resultList.push_back(result);
847 }
848 catch(ZorbaException const& /*err*/)
849 {
850 // do nothing here, the validator will throw the right error at end elemet event call
851 //std::cout << "validate.cpp: processTextValue2 '" << textValue << "' err:" << err.toString() << std::endl; std::cout.flush();
852 }
853 }
854 else
855 {
856 if ( GENV_ITEMFACTORY->createUntypedAtomic( result, textValue) )
857 resultList.push_back(result);
858 }
859 }
860 else
861 {
862 if ( GENV_ITEMFACTORY->createUntypedAtomic( result, textValue) )
863 resultList.push_back(result);
864 }
865 }
866
867 } // namespace zorba
868
869 #endif // ifndef ZORBA_NO_XMLSCHEMA
870 /* vim:set et sw=2 ts=2: */
871