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