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 <string>
19 
20 #include "compiler/parser/query_loc.h"
21 #include "context/namespace_context.h"
22 #include "context/static_context.h"
23 #include "context/uri_resolver.h"
24 
25 #include "zorbamisc/ns_consts.h"
26 #include "diagnostics/assert.h"
27 
28 #include "types/typeimpl.h"
29 #include "types/root_typemanager.h"
30 #include "types/typeops.h"
31 #include "types/casting.h"
32 #include "types/schema/schema.h"
33 #include "types/schema/StrX.h"
34 #include "types/schema/LoadSchemaErrorHandler.h"
35 #include "types/schema/PrintSchema.h"
36 #include "types/schema/XercesParseUtils.h"
37 #include "system/globalenv.h"
38 #include "store/api/item_factory.h"
39 #include "util/utf8_util.h"
40 #include "types/schema/xercesIncludes.h"
41 #include "zorbatypes/URI.h"
42 
43 #ifndef ZORBA_NO_XMLSCHEMA
44 # include <xercesc/util/XercesVersion.hpp>
45 # if XERCES_VERSION_MAJOR < 3
46     typedef unsigned int XMLFilePos;
47     typedef unsigned int Zorba_readBytes_type;
48 # else
49     typedef XMLSize_t Zorba_readBytes_type;
50 # endif
51 # include <xercesc/util/XercesDefs.hpp>
52 # include <xercesc/util/BinInputStream.hpp>
53 # include <zorbatypes/xerces_xmlcharray.h>
54 #endif /* ZORBA_NO_XMLSCHEMA */
55 
56 
57 #include "zorbaserialization/serialize_template_types.h"
58 #include "zorbaserialization/serialize_zorba_types.h"
59 
60 
61 namespace zorba
62 {
63 SERIALIZABLE_CLASS_VERSIONS(Schema)
64 
65 //#define DO_TRACE
66 //#define DO_PRINT_SCHEMA_INFO
67 
68 #ifdef DO_TRACE
69 
70 #define TRACE(msg)                                                            \
71   {                                                                           \
72     std::cout << __FUNCTION__ << ": " << msg << std::endl; std::cout.flush(); \
73   }
74 
75 #else
76 #define TRACE(msg)
77 #endif
78 
79 
80 const char* Schema::XSD_NAMESPACE = XML_SCHEMA_NS;
81 
82 bool Schema::theIsInitialized = false;
83 
84 #ifndef ZORBA_NO_XMLSCHEMA
85 
86 
transcode(const XMLCh * const str,zstring & res)87 static void transcode(const XMLCh* const str, zstring& res)
88 {
89   char* trStr = XMLString::transcode(str);
90   res = zstring(trStr);
91   XMLString::release(&trStr);
92 }
93 
94 
95 /**
96  * A Xerces BinInputStream that returns bytes from a std::istream.
97  */
98 class IstreamBinInputStream : public XERCES_CPP_NAMESPACE::BinInputStream
99 {
100 public:
IstreamBinInputStream(std::istream * aStream)101   IstreamBinInputStream(std::istream* aStream)
102     :
103     theStream(aStream)
104   {
105   }
106 
curPos() const107   virtual XMLFilePos curPos() const
108   {
109     return theStream->tellg();
110   }
111 
readBytes(XMLByte * const toFill,const Zorba_readBytes_type maxToRead)112   virtual Zorba_readBytes_type readBytes
113   (XMLByte * const toFill, const Zorba_readBytes_type maxToRead)
114   {
115     // QQQ Is this reinterpret_cast necessary? Is it safe? Can I just
116     // pump the chars from read() to the XMLBytes Xerces wants?
117     char* const lToFill = reinterpret_cast<char*>(toFill);
118     TRACE("lToFill: " << lToFill );
119     theStream->read(lToFill, maxToRead);
120     return static_cast<unsigned int>(theStream->gcount());
121   }
122 
getContentType() const123   virtual const XMLCh* getContentType() const
124   {
125     // Unless we know it, do what Xerces' implementation does: return 0
126     return 0;
127   }
128 
129 private:
130   std::istream* theStream;
131 };
132 
133 
134 /**
135  * A Xerces InputSource that returns a IstreamBinInputStream.
136  */
137 class IstreamInputSource : public XERCES_CPP_NAMESPACE::InputSource
138 {
139 public:
IstreamInputSource(std::istream * aStream,StreamReleaser aStreamReleaser)140   IstreamInputSource(std::istream* aStream, StreamReleaser aStreamReleaser)
141     : theStream(aStream),
142       theStreamReleaser(aStreamReleaser)
143   {
144   }
145 
~IstreamInputSource()146   ~IstreamInputSource()
147   {
148     if (theStreamReleaser)
149     {
150       theStreamReleaser(theStream);
151     }
152   }
153 
makeStream() const154   virtual XERCES_CPP_NAMESPACE::BinInputStream* makeStream() const
155   {
156     return new IstreamBinInputStream(theStream);
157   }
158 
159 private:
160   std::istream* theStream;
161   StreamReleaser theStreamReleaser;
162 };
163 
164 
165 /**
166  * A Xerces EntityResolver that looks for a specific URL and returns
167  * InputSource that reads from a particular std::istream.
168  */
169 class StaticContextEntityResolver :
170     public XERCES_CPP_NAMESPACE::EntityResolver
171 {
172 public:
173   /**
174    * EntityResolver method
175    */
resolveEntity(const XMLCh * const publicId,const XMLCh * const systemId)176   XERCES_CPP_NAMESPACE::InputSource* resolveEntity(
177     const XMLCh* const publicId,
178     const XMLCh* const systemId)
179   {
180     TRACE("pId: " << StrX(publicId) << "  sId: " << StrX(systemId));
181     if (XMLString::compareString(systemId, theLogicalURI) == 0)
182     {
183       TRACE("logiUri: " << StrX(theLogicalURI) << " physicalUri: " << StrX(thePhysicalURI));
184       // Pass memory ownership of the istream to the IstreamInputSource
185       InputSource* lRetval = new IstreamInputSource(theStream, theStreamReleaser);
186       theStreamReleaser = nullptr;
187 
188       lRetval->setSystemId(thePhysicalURI);
189       return lRetval;
190     }
191     else if (publicId==NULL && systemId==NULL)
192     {
193       TRACE("No systemId and no publicId provided.");
194       return NULL;
195     }
196     else
197     {
198       const XMLCh* lId;
199       bool isPublicId = false;
200       bool isSystemId = false;
201 
202       if (systemId==NULL)
203       {
204         TRACE("Resolving based on publicId: " << StrX(publicId));
205         lId = publicId;
206         isPublicId = true;
207       }
208       else   // publicId must be non-NULL since it was previously checked
209       {
210         TRACE("Resolving based on systemId: " << StrX(systemId));
211         lId = systemId;
212         isSystemId = true;
213       }
214 
215       std::auto_ptr<internal::Resource> lResource;
216 
217       zstring lStrId = StrX(lId).localForm();
218       zstring lResolved;
219 
220       URI lUri(lStrId);
221       if ( !lUri.is_absolute() )
222       {
223         // must be resolved based on the schema location thePhysicalURI
224         zstring fullBase(StrX(thePhysicalURI).localForm());
225         zstring::size_type i = fullBase.find_last_of("/");
226         zstring base = fullBase.substr(0, i == zstring::npos ? fullBase.length() : i+1);
227         URI resolvedURI( base, lUri.toString(), true);
228         lResolved = resolvedURI.toString();
229         TRACE("i: " << i << " base: " << base << " lUri: " << lUri << " lRes: " << lResolved);
230       }
231       else
232         lResolved = lStrId;
233 
234       try
235       {
236         TRACE("lId: " << StrX(lId) << " lResolved: " << lResolved << " thePhysURI: " << StrX(thePhysicalURI));
237         zstring lErrorMessage;
238         lResource = theSctx->resolve_uri(lResolved, internal::EntityData::SCHEMA, lErrorMessage);
239         internal::StreamResource* lStream =
240             dynamic_cast<internal::StreamResource*>(lResource.get());
241         if (lStream != NULL)
242         {
243           // Pass memory ownership of this istream to the new IstreamInputSource
244           InputSource* lRetval = new IstreamInputSource
245               (lStream->getStream(), lStream->getStreamReleaser());
246           lStream->setStreamReleaser(nullptr);
247 
248           XMLCh * lResolvedXMLCh = XMLString::transcode(lResolved.c_str());
249           if (isSystemId)
250             lRetval->setSystemId(lResolvedXMLCh);
251 
252           if (isPublicId)
253             lRetval->setPublicId(lResolvedXMLCh);
254 
255           // release lResolvedXMLCh since setSystemId and setPublicId are makeing their own copies
256           XMLString::release(&lResolvedXMLCh);
257 
258           return lRetval;
259         }
260         else
261           return NULL;
262       }
263       catch (ZorbaException const& e) {
264         TRACE("!!! ZorbaException: " << e );
265         if ( e.diagnostic() == zerr::ZXQP0029_URI_ACCESS_DENIED )
266         {
267           throw;
268         }
269         else
270         {
271           //don't throw let Xerces resolve it
272           return NULL;
273         }
274       }
275     }
276   }
277 
StaticContextEntityResolver(const XMLCh * const aLogicalURI,static_context * aSctx,internal::StreamResource * aStreamResource)278   StaticContextEntityResolver(
279     const XMLCh* const aLogicalURI,
280     static_context * aSctx,
281     internal::StreamResource* aStreamResource)
282     : theLogicalURI(aLogicalURI), theSctx(aSctx)
283   {
284     // Take memory ownership of the istream
285     theStream = aStreamResource->getStream();
286     theStreamReleaser = aStreamResource->getStreamReleaser();
287     aStreamResource->setStreamReleaser(nullptr);
288     // Take memory ownership of the translated system ID
289     thePhysicalURI = XERCES_CPP_NAMESPACE::XMLString::transcode
290       (aStreamResource->getStreamUrl().c_str());
291   }
292 
~StaticContextEntityResolver()293   ~StaticContextEntityResolver()
294   {
295     XERCES_CPP_NAMESPACE::XMLString::release(&thePhysicalURI);
296     if (theStreamReleaser) {
297       theStreamReleaser(theStream);
298     }
299   }
300 
301 private:
302   const XMLCh * theLogicalURI;
303   static_context * theSctx;
304   std::istream* theStream;
305   StreamReleaser theStreamReleaser;
306   XMLCh * thePhysicalURI;
307 };
308 
309 #endif //ZORBA_NO_XMLSCHEMA
310 
311 
312 /*******************************************************************************
313   Initialize the Xerces platform. Called from GlobalEnvironment::init().
314 *******************************************************************************/
initialize()315 void Schema::initialize()
316 {
317 #ifndef ZORBA_NO_XMLSCHEMA
318   if (theIsInitialized)
319     return;
320 
321   try
322   {
323     XERCES_CPP_NAMESPACE::XMLPlatformUtils::Initialize();
324     theIsInitialized = true;
325   }
326   catch (const XERCES_CPP_NAMESPACE::XMLException& toCatch)
327   {
328     std::cerr   << "Error during Xerces-C initialization! Message:\n"
329                 << StrX(toCatch.getMessage()) << std::endl;
330     return;
331   }
332 #endif
333 }
334 
335 
336 /*******************************************************************************
337   Terminate the Xerces platform. Called from GlobalEnvironment::destroy().
338 *******************************************************************************/
terminate()339 void Schema::terminate()
340 {
341 #ifndef ZORBA_NO_XMLSCHEMA
342   if (theIsInitialized)
343   {
344     XERCES_CPP_NAMESPACE::XMLPlatformUtils::Terminate();
345     theIsInitialized = false;
346   }
347 #endif
348 }
349 
350 
351 /*******************************************************************************
352 
353 *******************************************************************************/
Schema(TypeManager * tm)354 Schema::Schema(TypeManager* tm)
355   :
356   theTypeManager(tm)
357 {
358 #ifndef ZORBA_NO_XMLSCHEMA
359   theGrammarPool = new XMLGrammarPoolImpl(XMLPlatformUtils::fgMemoryManager);
360   // QQQ should be zstring
361   theUdTypesCache =
362   new HashMap<zstring, xqtref_t, HashMapZStringCmp>(64, false);
363 #endif
364 }
365 
366 
Schema(::zorba::serialization::Archiver & ar)367 Schema::Schema(::zorba::serialization::Archiver& ar)
368 {
369 #ifndef ZORBA_NO_XMLSCHEMA
370   initialize();
371   theGrammarPool = new XMLGrammarPoolImpl(XMLPlatformUtils::fgMemoryManager);
372 #endif
373 }
374 
375 
376 /*******************************************************************************
377 
378 *******************************************************************************/
~Schema()379 Schema::~Schema()
380 {
381 #ifndef ZORBA_NO_XMLSCHEMA
382   delete theGrammarPool;
383   delete theUdTypesCache;
384 #endif
385 }
386 
387 
388 
389 /*******************************************************************************
390   Prints out info about the current schema grammar
391 *******************************************************************************/
printXSDInfo(bool excludeBuiltIn)392 void Schema::printXSDInfo(bool excludeBuiltIn)
393 {
394 #ifndef ZORBA_NO_XMLSCHEMA
395   PrintSchema::printInfo(excludeBuiltIn, theGrammarPool);
396 #endif
397 }
398 
399 
400 #ifndef ZORBA_NO_XMLSCHEMA
401 
402 
403 /*******************************************************************************
404   Registers an imported schema into the curent grammar
405 *******************************************************************************/
registerXSD(const char * xsdURL,static_context * aSctx,internal::StreamResource * stream,const QueryLoc & loc)406 void Schema::registerXSD(const char* xsdURL,
407   static_context * aSctx,
408   internal::StreamResource* stream,
409   const QueryLoc& loc)
410 {
411   std::auto_ptr<SAX2XMLReader> parser;
412 
413   TRACE("url=" << xsdURL << " loc=" << loc);
414 
415   try
416   {
417     SAX2XMLReader* reader =
418       XMLReaderFactory::createXMLReader(XMLPlatformUtils::fgMemoryManager,
419 					theGrammarPool);
420 
421     parser.reset(reader);
422     // Perform namespace processing
423     parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
424     // Do not report attributes used for namespace declarations and optionally
425     // do not report original prefixed names
426     parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, false);
427     // Enable parser's schema support
428     parser->setFeature(XMLUni::fgXercesSchema, true);
429     // time and memory intensive to be disabled only if schema files
430     // previously checked
431     parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
432     // report all validation errors
433     parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
434     // validate only if schema is available
435     parser->setFeature(XMLUni::fgXercesDynamic, true);
436     // load the schema in the grammar pool
437     ////parser->setFeature(XMLUni::fgXercesLoadSchema, true);
438     // disables network resolver
439     parser->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, true);
440     // skip DTDs
441     parser->setFeature(XMLUni::fgXercesLoadExternalDTD, false);
442 
443     parser->setProperty(XMLUni::fgXercesScannerName,
444                         (void *)XMLUni::fgSGXMLScanner);
445 
446     LoadSchemaErrorHandler handler(loc);
447     parser->setErrorHandler(&handler);
448 
449     XMLChArray xerces_xsdURL(xsdURL);
450     StaticContextEntityResolver lEntityResolver(xerces_xsdURL.get(), aSctx, stream);
451     parser->setEntityResolver(&lEntityResolver);
452 
453     //this works but using loadProlog
454     //parser->loadGrammar("file:///location/file.xsd",
455     //                    Grammar::SchemaGrammarType, true);
456 
457     parser->loadGrammar(xsdURL, Grammar::SchemaGrammarType, true);
458 
459     if (handler.getSawErrors())
460     {
461       handler.resetErrors();
462     }
463   }
464   catch (const OutOfMemoryException&)
465   {
466     throw XQUERY_EXCEPTION( err::XQST0059,
467         ERROR_PARAMS( std::string(xsdURL), ZED( SchemaOutOfMemory )),
468         ERROR_LOC( loc ) );
469   }
470   catch (const XMLException& e)
471   {
472     throw XQUERY_EXCEPTION( err::XQST0059,
473         ERROR_PARAMS( std::string(xsdURL), ZED( SchemaParseError ), StrX(e.getMessage())),
474         ERROR_LOC( loc ) );
475   }
476   catch (const ZorbaException& /* e */)
477   {
478     throw;
479   }
480   catch (...)
481   {
482     throw XQUERY_EXCEPTION( err::XQST0059,
483         ERROR_PARAMS( std::string(xsdURL), ZED( SchemaUnexpected )),
484         ERROR_LOC( loc ) );
485   }
486 
487 #ifdef DO_PRINT_SCHEMA_INFO
488   // enable this to debug registered user defined schema types
489   printXSDInfo(true);
490 #endif
491 }
492 
493 
494 /*******************************************************************************
495   For the given element name find out its declared schema type
496 *******************************************************************************/
getTypeNameFromElementName(const store::Item * qname,store::Item_t & typeName,const QueryLoc & loc)497 void Schema::getTypeNameFromElementName(
498     const store::Item* qname,
499     store::Item_t& typeName,
500     const QueryLoc& loc)
501 {
502   XSTypeDefinition* typeDef = getTypeDefForElement(qname);
503 
504   if (!typeDef)
505   {
506     throw XQUERY_EXCEPTION(
507       err::XPST0008,
508       ERROR_PARAMS( qname->getStringValue(), ZED( SchemaElementName ) ),
509       ERROR_LOC( loc )
510     );
511   }
512 
513   const XMLCh* typeNameStr = typeDef->getName();
514   const XMLCh* typeUri = typeDef->getNamespace();
515 
516   GENV_ITEMFACTORY->createQName(typeName,
517                                 StrX(typeUri).localForm(),
518                                 "",
519                                 StrX(typeNameStr).localForm());
520 }
521 
522 
523 /*******************************************************************************
524   For a given global attribute find out its declared schema type
525 *******************************************************************************/
getTypeNameFromAttributeName(const store::Item * qname,store::Item_t & typeName,const QueryLoc & loc)526 void Schema::getTypeNameFromAttributeName(
527     const store::Item* qname,
528     store::Item_t& typeName,
529     const QueryLoc& loc)
530 {
531   XSTypeDefinition* typeDef = getTypeDefForAttribute(qname);
532 
533   if (!typeDef)
534   {
535     throw XQUERY_EXCEPTION(
536       err::XPST0008,
537       ERROR_PARAMS( qname->getStringValue(), ZED( SchemaAttributeName ) ),
538       ERROR_LOC( loc )
539     );
540   }
541 
542   const XMLCh* typeNameStr = typeDef->getName();
543   const XMLCh* typeUri = typeDef->getNamespace();
544 
545   GENV_ITEMFACTORY->createQName(typeName,
546                                 StrX(typeUri).localForm(),
547                                 "",
548                                 StrX(typeNameStr).localForm());
549 }
550 
551 
552 /*******************************************************************************
553   Returns an XQType for a global schema element definition if defined,
554   otherwise NULL
555 *******************************************************************************/
createXQTypeFromElementName(const TypeManager * typeManager,const store::Item * qname,const bool riseErrors,const QueryLoc & loc)556 xqtref_t Schema::createXQTypeFromElementName(
557     const TypeManager* typeManager,
558     const store::Item* qname,
559     const bool riseErrors,
560     const QueryLoc& loc)
561 {
562   TRACE("qn:" << qname->getLocalName() << " @ " <<
563         qname->getNamespace() );
564 
565   XSTypeDefinition* typeDef = getTypeDefForElement(qname);
566 
567   if (!riseErrors && !typeDef)
568       return NULL;
569 
570   if (!typeDef)
571   {
572     throw XQUERY_EXCEPTION(
573       err::XPST0008,
574       ERROR_PARAMS( qname->getStringValue(), ZED( SchemaElementName ) ),
575       ERROR_LOC( loc )
576     );
577   }
578 
579   xqtref_t res = createXQTypeFromTypeDefinition(typeManager, typeDef);
580   TRACE("res:" << res->get_qname()->getLocalName() << " @ " <<
581         res->get_qname()->getNamespace());
582 
583   return res;
584 }
585 
586 
587 /*******************************************************************************
588   Returns an XQType for a global schema attribute definition if defined,
589   otherwise NULL
590 *******************************************************************************/
createXQTypeFromAttributeName(const TypeManager * typeManager,const store::Item * qname,const bool riseErrors,const QueryLoc & loc)591 xqtref_t Schema::createXQTypeFromAttributeName(
592     const TypeManager* typeManager,
593     const store::Item* qname,
594     const bool riseErrors,
595     const QueryLoc& loc)
596 {
597   XSTypeDefinition* typeDef = getTypeDefForAttribute(qname);
598 
599   if (!riseErrors && !typeDef)
600       return NULL;
601 
602   if (!typeDef)
603   {
604     throw XQUERY_EXCEPTION(
605       err::XPST0008,
606       ERROR_PARAMS( qname->getStringValue(), ZED( SchemaAttributeName ) ),
607       ERROR_LOC( loc )
608     );
609   }
610 
611   return createXQTypeFromTypeDefinition(typeManager, typeDef);
612 }
613 
614 
615 /*******************************************************************************
616   Checks if the Type with the qname exists in the schema as a user-defined type
617   if it does than return an XQType for it, if not return NULL
618 *******************************************************************************/
createXQTypeFromTypeName(const TypeManager * typeManager,const store::Item * qname)619 xqtref_t Schema::createXQTypeFromTypeName(
620     const TypeManager* typeManager,
621     const store::Item* qname)
622 {
623   XSTypeDefinition* typeDef = NULL;
624   xqtref_t res;
625 
626   TRACE("typeManager: " << typeManager << " type qname: "
627         << qname->getLocalName() << "@"
628         << qname->getNamespace());
629 
630   if (theGrammarPool == NULL)
631         return NULL;
632 
633   const zstring& nsuri = qname->getNamespace();
634   const zstring& local = qname->getLocalName();
635 
636   // check the cache first
637   zstring key;
638   key.reserve(local.size() + nsuri.size() + 4);
639   key += local;
640   key += ":";
641   key += nsuri;
642   key += " ";
643   key += TypeOps::decode_quantifier(TypeConstants::QUANT_ONE);
644 
645   if( theUdTypesCache->get(key, res))
646     return res;
647 
648     // not found in cache, make a new one
649   XMLChArray xml_local(local.c_str());
650   XMLChArray xml_uri(nsuri.c_str());
651 
652   bool modelHasChanged;
653   XSModel* xsModel = theGrammarPool->getXSModel(modelHasChanged);
654 
655   typeDef = xsModel->getTypeDefinition(xml_local, xml_uri);
656 
657   if ( typeDef == NULL )
658   {
659     // Go through all the top level type and element definitions and
660     // add annonymous types to the cache
661     //( maybe stop whenever it's found - a small optimization )
662     // this is required only when the multiple queries are executed in
663     // the same run with the current API, but with empty schema context
664 
665     TRACE("lookingFor: key:'" << key);
666     checkForAnonymousTypes(typeManager);
667 
668     if( theUdTypesCache->get(key, res))
669       return res;
670 
671     res = NULL;
672     TRACE("No type definition for " << xml_local << "@" << xml_uri);
673     TRACE("add to TypesCache: key:'" << key << "'  t:"
674           << ( res==NULL ? "NULL" :
675                TypeOps::decode_quantifier(res->get_quantifier())) );
676     // stick it in the cache even if it's NULL
677     theUdTypesCache->insert(key, res);
678   }
679   else
680   {
681     res = createXQTypeFromTypeDefinition(typeManager, typeDef);
682   }
683 
684   return res;
685 }
686 
687 
688 /*******************************************************************************
689   Get the the head of the substitution group, if any, that a given globally
690   declared element belongs to.
691 *******************************************************************************/
getSubstitutionHeadForElement(const store::Item * qname,store::Item_t & result)692 void Schema::getSubstitutionHeadForElement(
693     const store::Item* qname,
694     store::Item_t& result)
695 {
696   TRACE(" element qname: " << qname->getLocalName() << "@"
697         << qname->getNamespace());
698 
699   result = NULL;
700 
701   if (theGrammarPool == NULL)
702     return;
703 
704   XMLChArray local(qname->getLocalName().c_str());
705   XMLChArray uri(qname->getNamespace().c_str());
706 
707   bool xsModelWasChanged;
708   XSModel* model = theGrammarPool->getXSModel(xsModelWasChanged);
709 
710   XSElementDeclaration* decl = model->getElementDeclaration(local, uri);
711 
712   if (decl)
713   {
714     XSElementDeclaration* substHead = decl->getSubstitutionGroupAffiliation();
715 
716     if (substHead)
717     {
718       const XMLCh* localName = substHead->getName();
719       const XMLCh* nsuri = substHead->getNamespace();
720 
721       zstring lLocal;
722       transcode(localName, lLocal);
723       zstring lNamespace;
724       transcode(nsuri, lNamespace);
725 
726       GENV_ITEMFACTORY->createQName(result, lNamespace, zstring(), lLocal);
727     }
728   }
729 }
730 
731 
732 /*******************************************************************************
733   Get the type definition for a globally declared element
734 *******************************************************************************/
getTypeDefForElement(const store::Item * qname)735 XSTypeDefinition* Schema::getTypeDefForElement(const store::Item* qname)
736 {
737   XSTypeDefinition* typeDef = NULL;
738 
739   TRACE(" element qname: " << qname->getLocalName() << "@" <<
740         qname->getNamespace());
741 
742   if (theGrammarPool == NULL)
743     return NULL;
744 
745   XMLChArray local(qname->getLocalName().c_str());
746   XMLChArray uri(qname->getNamespace().c_str());
747 
748   bool xsModelWasChanged;
749   XSModel* model = theGrammarPool->getXSModel(xsModelWasChanged);
750 
751   XSElementDeclaration* decl = model->getElementDeclaration(local, uri);
752 
753   if (decl)
754   {
755     typeDef = decl->getTypeDefinition();
756 
757     // this works only on the element that is a substitution,
758     // not on substitution base element
759     //XSElementDeclaration * substGroup =
760     //  decl->getSubstitutionGroupAffiliation();
761 
762     //if ( substGroup )
763     //{
764     //    TRACE(" substitutionGroup qname: " << StrX(substGroup->getName()) <<
765     //      "@" << StrX(substGroup->getNamespace()) << "\n");
766     //}
767   }
768 
769   return typeDef;
770 }
771 
772 
773 /*******************************************************************************
774   Get the type definition for a globally declared attribute
775 *******************************************************************************/
getTypeDefForAttribute(const store::Item * qname)776 XSTypeDefinition* Schema::getTypeDefForAttribute(const store::Item* qname)
777 {
778   XSTypeDefinition* typeDef = NULL;
779 
780   TRACE(" attribute qname: " << qname->getLocalName() << "@" <<
781         qname->getNamespace());
782 
783   if (theGrammarPool == NULL)
784     return NULL;
785 
786   XMLChArray local(qname->getLocalName().c_str());
787   XMLChArray uri(qname->getNamespace().c_str());
788 
789   bool xsModelWasChanged;
790   XSModel* model = theGrammarPool->getXSModel(xsModelWasChanged);
791 
792   XSAttributeDeclaration* decl = model->getAttributeDeclaration(local, uri);
793 
794   if (decl)
795     typeDef = decl->getTypeDefinition();
796 
797   return typeDef;
798 }
799 
800 
801 /*******************************************************************************
802   Creates a zorba schema type for a schema type definition
803 *******************************************************************************/
createXQTypeFromTypeDefinition(const TypeManager * typeManager,XSTypeDefinition * xsTypeDef)804 xqtref_t Schema::createXQTypeFromTypeDefinition(
805     const TypeManager* typeManager,
806     XSTypeDefinition* xsTypeDef)
807 {
808   if (!xsTypeDef)
809   {
810     ZORBA_ASSERT(false);
811     return NULL;
812   }
813 
814   xqtref_t result;
815 
816   if (xsTypeDef->getTypeCategory() == XSTypeDefinition::SIMPLE_TYPE)
817   {
818     // first check if it is a built-in type
819     const XMLCh* uri = xsTypeDef->getNamespace();
820     zstring strUri;
821     transcode(uri, strUri);
822 
823     if ( XMLString::equals(strUri.c_str(), Schema::XSD_NAMESPACE) )
824     {
825       const XMLCh* local = xsTypeDef->getName();
826 
827       result = createXQTypeFromTypeDefForBuiltinTypes(typeManager, strUri,
828                                                       local);
829     }
830     else
831     {
832       // must be a user defined simple type
833       XSSimpleTypeDefinition * xsSimpleTypeDef =
834         (XSSimpleTypeDefinition *)xsTypeDef;
835 
836       zstring lLocal;
837       transcode(xsTypeDef->getName(), lLocal);
838 
839       store::Item_t qname;
840       GENV_ITEMFACTORY->createQName(qname, strUri, zstring(), lLocal);
841       TRACE("createXQType " << qname->getStringValue() );
842 
843       switch ( xsSimpleTypeDef->getVariety() )
844       {
845       case XSSimpleTypeDefinition::VARIETY_ATOMIC:
846       {
847         XSTypeDefinition* baseTypeDef = xsTypeDef->getBaseType();
848         if ( !baseTypeDef )
849         {
850           //error allway must have a baseType
851           ZORBA_ASSERT(false);
852           result = NULL;
853         }
854 
855         xqtref_t baseXQType = createXQTypeFromTypeDefinition(typeManager,
856             baseTypeDef);
857 
858         xqtref_t xqType = xqtref_t(new UserDefinedXQType(typeManager,
859                                                  qname,
860                                                  baseXQType,
861                                                  TypeConstants::QUANT_ONE,
862                                                  UserDefinedXQType::ATOMIC_TYPE,
863                                                  XQType::SIMPLE_CONTENT_KIND));
864         TRACE("created atomic " << qname->getStringValue() << " base:" << baseXQType->toString());
865         result = xqType;
866       }
867       break;
868 
869       case XSSimpleTypeDefinition::VARIETY_LIST:
870       {
871         XSSimpleTypeDefinition * itemTypeDef = xsSimpleTypeDef->getItemType();
872         if ( !itemTypeDef )
873         {
874           //error since VARIETY is LIST must have an itemType
875           ZORBA_ASSERT(false);
876           result = NULL;
877         }
878         xqtref_t itemXQType = createXQTypeFromTypeDefinition(typeManager,
879             itemTypeDef);
880 
881         if ( itemXQType->type_kind() == XQType::USER_DEFINED_KIND )
882         {   // if UDT add it to the cache, otherwise it will get lost
883           addTypeToCache(itemXQType);
884         }
885 
886         //cout << " creating UDT Simple List Type: " <<
887         //  qname->getLocalName()->c_str() <<  "@" <<
888         //  qname->getNamespace()->c_str() << " of " << itemXQType->toString()
889         //    << endl; cout.flush();
890 
891         xqtref_t xqType = xqtref_t(
892             new UserDefinedXQType(typeManager,
893                                   qname,
894                                   NULL /*GENV_TYPESYSTEM.ANY_SIMPLE_TYPE*/,
895                                   TypeConstants::QUANT_ONE,
896                                   itemXQType.getp()));
897 
898         //cout << "   created UDT Simple List Type: " << xqType->toString() <<
899         //  endl; cout.flush();
900         addTypeToCache(xqType);
901 
902         result = xqType;
903       }
904       break;
905 
906       case XSSimpleTypeDefinition::VARIETY_UNION:
907       {
908         XSSimpleTypeDefinitionList * memberTypesDefList =
909             xsSimpleTypeDef->getMemberTypes();
910 
911         if ( !memberTypesDefList )
912         {
913           //error since VARIETY is UNION must have a memberTypesDefList
914           ZORBA_ASSERT(false);
915           result = NULL;
916         }
917 
918         //cout << " creating UDT Simple Union Type: " <<
919         // qname->getLocalName()->c_str() << "@" <<
920         // qname->getNamespace()->c_str() << " of: ";
921         std::vector<xqtref_t> unionItemTypes;
922 
923         for ( unsigned int i = 0; i < memberTypesDefList->size(); i++)
924         {
925           XSSimpleTypeDefinition* itemTypeDef =
926             memberTypesDefList->elementAt(i);
927           xqtref_t itemXQType = createXQTypeFromTypeDefinition(typeManager,
928                                                                itemTypeDef);
929           unionItemTypes.push_back(itemXQType);
930           //cout << " " << itemXQType->toString();
931 
932           if ( itemXQType->type_kind() == XQType::USER_DEFINED_KIND )
933           {   // if UDT add it to the cache, otherwise it will get lost
934             addTypeToCache(itemXQType);
935           }
936         }
937         //cout << endl; cout.flush();
938 
939         xqtref_t xqType = xqtref_t(
940             new UserDefinedXQType(typeManager,
941                                   qname,
942                                   NULL /*GENV_TYPESYSTEM.ANY_SIMPLE_TYPE*/,
943                                   TypeConstants::QUANT_ONE,
944                                   unionItemTypes));
945 
946         //cout << "   created UDT Union Type: " << xqType->toString() << endl;
947         //  cout.flush();
948         addTypeToCache(xqType);
949 
950         result = xqType;
951       }
952       break;
953 
954       case XSSimpleTypeDefinition::VARIETY_ABSENT:
955         // Xerces source says it must be anySimpleType
956         result = GENV_TYPESYSTEM.ANY_SIMPLE_TYPE;
957         break;
958 
959       default:
960         ZORBA_ASSERT(false);
961       }
962 
963       checkForAnonymousTypesInType(typeManager, xsTypeDef);
964 
965     } // end user defined simple types
966   }     // end simple types
967   else
968   {
969     // is not a simple type has to be complex
970     ZORBA_ASSERT( xsTypeDef->getTypeCategory()==XSTypeDefinition::COMPLEX_TYPE);
971 
972     // first check if it is a built-in type
973     const XMLCh* uri = xsTypeDef->getNamespace();
974     zstring strUri;
975     transcode(uri, strUri);
976 
977     if ( XMLString::equals(strUri.c_str(), Schema::XSD_NAMESPACE) )
978     {
979       const XMLCh* local = xsTypeDef->getName();
980       // maybe there is a better way than comparing strings
981       // but it seems Xerces doesn't have a code for built-in types
982       if ( XMLString::equals(XMLChArray("anyType").get(), local) )
983       {
984         result = GENV_TYPESYSTEM.ANY_TYPE;
985       }
986       else if ( XMLString::equals(XMLChArray("untyped").get(), local) )
987       {
988         result = GENV_TYPESYSTEM.UNTYPED_TYPE;
989       }
990       else
991       {
992         // there are no other non simple known types in xsd namespace
993         ZORBA_ASSERT(false);
994       }
995     }
996     else
997     {
998       // user defined complex Type
999       XSTypeDefinition* baseTypeDef = xsTypeDef->getBaseType();
1000       if ( !baseTypeDef )
1001       {
1002         //error allways must have a baseType
1003         ZORBA_ASSERT(false);
1004         result = NULL;
1005       }
1006 
1007       xqtref_t baseXQType = createXQTypeFromTypeDefinition(typeManager,
1008                                                            baseTypeDef);
1009 
1010       zstring lLocal;
1011       transcode(xsTypeDef->getName(), lLocal);
1012 
1013       store::Item_t qname;
1014       GENV_ITEMFACTORY->createQName(qname, strUri, zstring(), lLocal);
1015 
1016       TRACE("udComplexType: " << StrX(xsTypeDef->getName()) << " @ " <<
1017             StrX(xsTypeDef->getNamespace()) );
1018 
1019       // get content type
1020       XSComplexTypeDefinition* xsComplexTypeDef =
1021         static_cast<XSComplexTypeDefinition*>(xsTypeDef);
1022 
1023       XQType::content_kind_t contentType;
1024 
1025       switch(xsComplexTypeDef->getContentType())
1026       {
1027       case XSComplexTypeDefinition::CONTENTTYPE_MIXED:
1028         contentType = XQType::MIXED_CONTENT_KIND;
1029         break;
1030       case XSComplexTypeDefinition::CONTENTTYPE_ELEMENT:
1031         contentType = XQType::ELEMENT_ONLY_CONTENT_KIND;
1032         break;
1033       case XSComplexTypeDefinition::CONTENTTYPE_SIMPLE:
1034         contentType = XQType::SIMPLE_CONTENT_KIND;
1035         break;
1036       case XSComplexTypeDefinition::CONTENTTYPE_EMPTY:
1037         contentType = XQType::EMPTY_CONTENT_KIND;
1038         break;
1039       default:
1040         ZORBA_ASSERT(false);
1041       }
1042 
1043       xqtref_t xqType =
1044             xqtref_t(new UserDefinedXQType(typeManager,
1045                                            qname,
1046                                            baseXQType,
1047                                            TypeConstants::QUANT_ONE,
1048                                            UserDefinedXQType::COMPLEX_TYPE,
1049                                            contentType));
1050 
1051       result = xqType;
1052 
1053       addTypeToCache(xqType);
1054 
1055       //check if it contains anonymous types (they are not available through
1056       //  xsModel API) add them to the cache
1057       checkForAnonymousTypesInType(typeManager, xsTypeDef);
1058     }
1059   }
1060 
1061   return result;
1062 }
1063 
1064 
createXQTypeFromTypeDefForBuiltinTypes(const TypeManager * typeManager,zstring & strUri,const XMLCh * local)1065 xqtref_t Schema::createXQTypeFromTypeDefForBuiltinTypes(
1066     const TypeManager* typeManager, zstring& strUri,
1067     const XMLCh* local)
1068 {
1069   xqtref_t result;
1070 
1071   ZORBA_ASSERT( XMLString::equals(strUri.c_str(), Schema::XSD_NAMESPACE) );
1072 
1073   // maybe there is a better way than comparing strings
1074   // but it seems Xerces doesn't have a code for built-in types
1075   if ( XMLString::equals(SchemaSymbols::fgDT_STRING, local) )
1076   {
1077     result = GENV_TYPESYSTEM.STRING_TYPE_ONE;
1078   }
1079   else if ( XMLString::equals(SchemaSymbols::fgDT_INT, local) )
1080   {
1081     result = GENV_TYPESYSTEM.INT_TYPE_ONE;
1082   }
1083   else if ( XMLString::equals(SchemaSymbols::fgDT_BOOLEAN, local) )
1084   {
1085     result = GENV_TYPESYSTEM.BOOLEAN_TYPE_ONE;
1086   }
1087   else if ( XMLString::equals(SchemaSymbols::fgDT_INTEGER, local) )
1088   {
1089     result = GENV_TYPESYSTEM.INTEGER_TYPE_ONE;
1090   }
1091   else if ( XMLString::equals(SchemaSymbols::fgDT_POSITIVEINTEGER, local) )
1092   {
1093     result = GENV_TYPESYSTEM.POSITIVE_INTEGER_TYPE_ONE;
1094   }
1095   else if ( XMLString::equals(SchemaSymbols::fgDT_NONPOSITIVEINTEGER, local) )
1096   {
1097     result = GENV_TYPESYSTEM.NON_POSITIVE_INTEGER_TYPE_ONE;
1098   }
1099   else if ( XMLString::equals(SchemaSymbols::fgDT_NEGATIVEINTEGER, local) )
1100   {
1101     result = GENV_TYPESYSTEM.NEGATIVE_INTEGER_TYPE_ONE;
1102   }
1103   else if ( XMLString::equals(SchemaSymbols::fgDT_NONNEGATIVEINTEGER, local) )
1104   {
1105     result = GENV_TYPESYSTEM.NON_NEGATIVE_INTEGER_TYPE_ONE;
1106   }
1107   else if ( XMLString::equals(SchemaSymbols::fgDT_UBYTE, local) )
1108   {
1109     result = GENV_TYPESYSTEM.UNSIGNED_BYTE_TYPE_ONE;
1110   }
1111   else if ( XMLString::equals(SchemaSymbols::fgDT_USHORT, local) )
1112   {
1113     result = GENV_TYPESYSTEM.UNSIGNED_SHORT_TYPE_ONE;
1114   }
1115   else if ( XMLString::equals(SchemaSymbols::fgDT_UINT, local) )
1116   {
1117     result = GENV_TYPESYSTEM.UNSIGNED_INT_TYPE_ONE;
1118   }
1119   else if ( XMLString::equals(SchemaSymbols::fgDT_ULONG, local) )
1120   {
1121     result = GENV_TYPESYSTEM.UNSIGNED_LONG_TYPE_ONE;
1122   }
1123   else if ( XMLString::equals(SchemaSymbols::fgDT_BYTE, local) )
1124   {
1125     result = GENV_TYPESYSTEM.BYTE_TYPE_ONE;
1126   }
1127   else if ( XMLString::equals(SchemaSymbols::fgDT_SHORT, local) )
1128   {
1129     result = GENV_TYPESYSTEM.SHORT_TYPE_ONE;
1130   }
1131   else if ( XMLString::equals(SchemaSymbols::fgDT_LONG, local) )
1132   {
1133     result = GENV_TYPESYSTEM.LONG_TYPE_ONE;
1134   }
1135   else if ( XMLString::equals(SchemaSymbols::fgDT_FLOAT, local) )
1136   {
1137     result = GENV_TYPESYSTEM.FLOAT_TYPE_ONE;
1138   }
1139   else if ( XMLString::equals(SchemaSymbols::fgDT_DOUBLE, local) )
1140   {
1141     result = GENV_TYPESYSTEM.DOUBLE_TYPE_ONE;
1142   }
1143   else if ( XMLString::equals(SchemaSymbols::fgDT_DECIMAL, local) )
1144   {
1145     result = GENV_TYPESYSTEM.DECIMAL_TYPE_ONE;
1146   }
1147   else if ( XMLString::equals(SchemaSymbols::fgDT_NORMALIZEDSTRING, local) )
1148   {
1149     result = GENV_TYPESYSTEM.NORMALIZED_STRING_TYPE_ONE;
1150   }
1151   else if ( XMLString::equals(SchemaSymbols::fgDT_TOKEN, local) )
1152   {
1153     result = GENV_TYPESYSTEM.TOKEN_TYPE_ONE;
1154   }
1155   else if ( XMLString::equals(SchemaSymbols::fgDT_NAME, local) )
1156   {
1157     result = GENV_TYPESYSTEM.NAME_TYPE_ONE;
1158   }
1159   else if ( XMLString::equals(SchemaSymbols::fgDT_NCNAME, local) )
1160   {
1161     result = GENV_TYPESYSTEM.NCNAME_TYPE_ONE;
1162   }
1163   else if ( XMLString::equals(SchemaSymbols::fgDT_DATETIME, local) )
1164   {
1165     result = GENV_TYPESYSTEM.DATETIME_TYPE_ONE;
1166   }
1167   else if ( XMLString::equals(SchemaSymbols::fgDT_DATE, local) )
1168   {
1169     result = GENV_TYPESYSTEM.DATE_TYPE_ONE;
1170   }
1171   else if ( XMLString::equals(SchemaSymbols::fgDT_TIME, local) )
1172   {
1173     result = GENV_TYPESYSTEM.TIME_TYPE_ONE;
1174   }
1175   else if ( XMLString::equals(SchemaSymbols::fgDT_YEAR, local) )
1176   {
1177     result = GENV_TYPESYSTEM.GYEAR_TYPE_ONE;
1178   }
1179   else if ( XMLString::equals(SchemaSymbols::fgDT_YEARMONTH, local) )
1180   {
1181     result = GENV_TYPESYSTEM.GYEAR_MONTH_TYPE_ONE;
1182   }
1183   else if ( XMLString::equals(SchemaSymbols::fgDT_MONTHDAY, local) )
1184   {
1185     result = GENV_TYPESYSTEM.GMONTH_DAY_TYPE_ONE;
1186   }
1187   else if ( XMLString::equals(SchemaSymbols::fgDT_DAY, local) )
1188   {
1189     result = GENV_TYPESYSTEM.GDAY_TYPE_ONE;
1190   }
1191   else if ( XMLString::equals(SchemaSymbols::fgDT_MONTH, local) )
1192   {
1193     result = GENV_TYPESYSTEM.GMONTH_TYPE_ONE;
1194   }
1195   else if ( XMLString::equals(SchemaSymbols::fgDT_DURATION, local) )
1196   {
1197     result = GENV_TYPESYSTEM.DURATION_TYPE_ONE;
1198   }
1199   else if ( XMLString::equals(SchemaSymbols::fgDT_ANYSIMPLETYPE, local) )
1200   {
1201     result = GENV_TYPESYSTEM.ANY_SIMPLE_TYPE;
1202   }
1203   else if ( XMLString::equals(SchemaSymbols::fgDT_BASE64BINARY, local) )
1204   {
1205     result = GENV_TYPESYSTEM.BASE64BINARY_TYPE_ONE;
1206   }
1207   else if ( XMLString::equals(SchemaSymbols::fgDT_HEXBINARY, local) )
1208   {
1209     result = GENV_TYPESYSTEM.HEXBINARY_TYPE_ONE;
1210   }
1211   else if ( XMLString::equals(SchemaSymbols::fgDT_ANYURI, local) )
1212   {
1213     result = GENV_TYPESYSTEM.ANY_URI_TYPE_ONE;
1214   }
1215   else if ( XMLString::equals(SchemaSymbols::fgDT_QNAME, local) )
1216   {
1217     result = GENV_TYPESYSTEM.QNAME_TYPE_ONE;
1218   }
1219   else if ( XMLString::equals(SchemaSymbols::fgATTVAL_ID, local) )
1220   {
1221     result = GENV_TYPESYSTEM.ID_TYPE_ONE;
1222   }
1223   // SchemaSymbols::fgDT_NMTOKEN doesn't exist in Xerces
1224   else if ( XMLString::equals(XMLChArray("NMTOKEN").get (), local) )
1225   {
1226     result = GENV_TYPESYSTEM.NMTOKEN_TYPE_ONE;
1227   }
1228   else if ( XMLString::equals(XMLChArray("NMTOKENS").get (), local) )
1229   {
1230 	store::Item_t qname;
1231 	GENV_ITEMFACTORY->createQName(qname,
1232 								  XML_SCHEMA_NS,
1233 								  "XS",
1234 								  "NMTOKENS");
1235 
1236 	result = new UserDefinedXQType(typeManager,
1237 								   qname,
1238 								   NULL,
1239 								   TypeConstants::QUANT_ONE,
1240 								   GENV_TYPESYSTEM.NMTOKEN_TYPE_ONE.getp());
1241   }
1242   else if ( XMLString::equals(XMLChArray("IDREF").get (), local) )
1243   {
1244     result = GENV_TYPESYSTEM.IDREF_TYPE_ONE;
1245   }
1246   else if ( XMLString::equals(XMLChArray("IDREFS").get (), local) )
1247   {
1248     store::Item_t qname;
1249     GENV_ITEMFACTORY->createQName(qname,
1250                                   XML_SCHEMA_NS,
1251                                   "XS",
1252                                   "IDREFS");
1253 
1254     result = new UserDefinedXQType(typeManager,
1255                                    qname,
1256                                    NULL,
1257                                    TypeConstants::QUANT_ONE,
1258                                    GENV_TYPESYSTEM.IDREF_TYPE_ONE.getp());
1259   }
1260   else if ( XMLString::equals(XMLChArray("ENTITY").get (), local) )
1261   {
1262     store::Item_t qname;
1263     GENV_ITEMFACTORY->createQName(qname,
1264                                   XML_SCHEMA_NS,
1265                                   "XS",
1266                                   "ENTITIES");
1267 
1268     result = new UserDefinedXQType(typeManager,
1269                                    qname,
1270                                    NULL,
1271                                    TypeConstants::QUANT_ONE,
1272                                    GENV_TYPESYSTEM.ENTITY_TYPE_ONE.getp());
1273   }
1274   else if ( XMLString::equals(XMLChArray("ENTITIES").get (), local) )
1275   {
1276     result = GENV_TYPESYSTEM.ENTITY_TYPE_PLUS;
1277   }
1278   else if ( XMLString::equals(XMLChArray("NOTATION").get (), local) )
1279   {
1280     result = GENV_TYPESYSTEM.NOTATION_TYPE_ONE;
1281   }
1282   else if ( XMLString::equals(XMLChArray("language").get (), local) )
1283   {
1284     result = GENV_TYPESYSTEM.LANGUAGE_TYPE_ONE;
1285   }
1286   // YearMonthDuration and DayTimeDuration are not in schema spec
1287   else
1288   {
1289     // type not covered
1290     std::cout << "Assertion Error: Type unknown " << StrX(local).localForm() <<
1291       "@" << Schema::XSD_NAMESPACE; std::cout.flush();
1292     ZORBA_ASSERT(false);
1293     result = NULL;
1294   }
1295 
1296   return result;
1297 }
1298 
1299 
checkForAnonymousTypes(const TypeManager * typeManager)1300 void Schema::checkForAnonymousTypes(const TypeManager* typeManager)
1301 {
1302   if (theGrammarPool == NULL)
1303     return;
1304 
1305   bool xsModelWasChanged;
1306   XSModel* model = theGrammarPool->getXSModel(xsModelWasChanged);
1307 
1308   XSNamedMap<XSObject> * typeDefs =
1309       model->getComponents(XSConstants::TYPE_DEFINITION);
1310   for( uint i = 0; i<typeDefs->getLength(); i++)
1311   {
1312     XSTypeDefinition* typeDef = (XSTypeDefinition*)(typeDefs->item(i));
1313     checkForAnonymousTypesInType(typeManager, typeDef);
1314   }
1315 
1316   XSNamedMap<XSObject> * elemDefs =
1317       model->getComponents(XSConstants::ELEMENT_DECLARATION);
1318   for( uint i = 0; i<elemDefs->getLength(); i++)
1319   {
1320     XSElementDeclaration* elemDecl = (XSElementDeclaration*)(elemDefs->item(i));
1321     checkForAnonymousTypesInType(typeManager, elemDecl->getTypeDefinition());
1322     // only if typeDef is Anonymous will be added to the cache
1323     addAnonymousTypeToCache(typeManager, elemDecl->getTypeDefinition());
1324   }
1325 
1326   XSNamedMap<XSObject> * attrDefs =
1327       model->getComponents(XSConstants::ATTRIBUTE_DECLARATION);
1328   for( uint i = 0; i<attrDefs->getLength(); i++)
1329   {
1330     XSAttributeDeclaration* attrDecl =
1331         (XSAttributeDeclaration*)(attrDefs->item(i));
1332     checkForAnonymousTypesInType(typeManager, attrDecl->getTypeDefinition());
1333     // only if typeDef is Anonymous will be added to the cache
1334     addAnonymousTypeToCache(typeManager, attrDecl->getTypeDefinition());
1335   }
1336 
1337   XSNamedMap<XSObject> * attrGroupDefs =
1338       model->getComponents(XSConstants::ATTRIBUTE_GROUP_DEFINITION);
1339   for( uint i = 0; i<attrGroupDefs->getLength(); i++)
1340   {
1341     XSAttributeGroupDefinition* attrGroupDef =
1342         (XSAttributeGroupDefinition*)(attrGroupDefs->item(i));
1343     XSAttributeUseList* xsAttributeUseList = attrGroupDef->getAttributeUses();
1344     if (xsAttributeUseList)
1345     {
1346       for (unsigned i = 0; i < xsAttributeUseList->size(); i++)
1347       {
1348         XSAttributeDeclaration* attrDecl = xsAttributeUseList->elementAt(i)->
1349           getAttrDeclaration();
1350         checkForAnonymousTypesInType(typeManager, attrDecl->getTypeDefinition());
1351       }
1352     }
1353   }
1354 
1355   XSNamedMap<XSObject> * modelGroupDefs =
1356       model->getComponents(XSConstants::MODEL_GROUP_DEFINITION);
1357   for( uint i = 0; i<modelGroupDefs->getLength(); i++)
1358   {
1359     XSModelGroupDefinition* modelGroupDef =
1360         (XSModelGroupDefinition*)modelGroupDefs->item(i);
1361     XSModelGroup *xsModelGroup = modelGroupDef->getModelGroup();
1362     if (xsModelGroup)
1363     {
1364       XSParticleList *xsParticleList = xsModelGroup->getParticles();
1365       if (xsParticleList)
1366       {
1367         for (unsigned i = 0; i < xsParticleList->size(); i++)
1368         {
1369           checkForAnonymousTypesInParticle(typeManager,
1370                                            xsParticleList->elementAt(i));
1371         }
1372       }
1373     }
1374   }
1375 }
1376 
checkForAnonymousTypesInType(const TypeManager * typeManager,XSTypeDefinition * xsTypeDef)1377 void Schema::checkForAnonymousTypesInType(const TypeManager* typeManager,
1378                                           XSTypeDefinition* xsTypeDef)
1379 {
1380     TRACE(" type: " << StrX(xsTypeDef->getName()) << "@" <<
1381         StrX(xsTypeDef->getNamespace()));
1382 
1383     XSTypeDefinition *xsBaseTypeDef = xsTypeDef->getBaseType();
1384     if (xsBaseTypeDef)
1385     {
1386         addAnonymousTypeToCache(typeManager, xsBaseTypeDef);
1387     }
1388 
1389     if (xsTypeDef->getTypeCategory() == XSTypeDefinition::SIMPLE_TYPE)
1390     {
1391         // Simple
1392         // to do list, union ??
1393     }
1394     else
1395     {
1396         // Complex
1397         XSComplexTypeDefinition* xsComplexTypeDef =
1398             static_cast<XSComplexTypeDefinition*>(xsTypeDef);
1399         XSComplexTypeDefinition::CONTENT_TYPE contentType =
1400             xsComplexTypeDef->getContentType();
1401 
1402         if (contentType == XSComplexTypeDefinition::CONTENTTYPE_ELEMENT
1403           || contentType == XSComplexTypeDefinition::CONTENTTYPE_MIXED)
1404         {
1405             XSParticle *xsParticle = xsComplexTypeDef->getParticle();
1406             checkForAnonymousTypesInParticle(typeManager, xsParticle);
1407         }
1408     }
1409 }
1410 
checkForAnonymousTypesInParticle(const TypeManager * typeManager,XSParticle * xsParticle)1411 void Schema::checkForAnonymousTypesInParticle(const TypeManager* typeManager,
1412     XSParticle *xsParticle)
1413 {
1414     if (!xsParticle)
1415         return;
1416 
1417     if ( xsParticle->getName() )
1418     {
1419         TRACE(" particle: " << StrX(xsParticle->getName()) << " @" <<
1420             StrX(xsParticle->getNamespace()));
1421     }
1422 
1423     XSParticle::TERM_TYPE termType = xsParticle->getTermType();
1424     if (termType == XSParticle::TERM_ELEMENT)
1425     {
1426         XSElementDeclaration *xsElement = xsParticle->getElementTerm();
1427 
1428         if ( xsElement->getScope() != XSConstants::SCOPE_GLOBAL )
1429         {
1430           // if reference to a global definition skip it,
1431           // otherwise infinite loop
1432           XSTypeDefinition* xsParticleTypeDef = xsElement->getTypeDefinition();
1433           addAnonymousTypeToCache(typeManager, xsParticleTypeDef);
1434         }
1435     }
1436     else if (termType == XSParticle::TERM_MODELGROUP)
1437     {
1438         XSModelGroup *xsModelGroup = xsParticle->getModelGroupTerm();
1439 
1440         XSParticleList *xsParticleList = xsModelGroup->getParticles();
1441         for (unsigned i = 0; i < xsParticleList->size(); i++)
1442         {
1443             checkForAnonymousTypesInParticle(typeManager,
1444                 xsParticleList->elementAt(i));
1445         }
1446     }
1447 }
1448 
1449 
addAnonymousTypeToCache(const TypeManager * typeManager,XSTypeDefinition * xsTypeDef)1450 void Schema::addAnonymousTypeToCache(
1451     const TypeManager* typeManager,
1452     XSTypeDefinition* xsTypeDef)
1453 {
1454   if (!xsTypeDef->getAnonymous())
1455     return;
1456 
1457   XSTypeDefinition* baseTypeDef = xsTypeDef->getBaseType();
1458   if (!baseTypeDef) {
1459     //error allways must have a baseType
1460     ZORBA_ASSERT(false);
1461     return;
1462   }
1463 
1464   xqtref_t baseXQType =
1465     createXQTypeFromTypeDefinition(typeManager, baseTypeDef);
1466 
1467   const XMLCh* uri = xsTypeDef->getNamespace();
1468   zstring strUri;
1469   transcode(uri, strUri);
1470   zstring lLocal;
1471   transcode(xsTypeDef->getName(), lLocal);
1472 
1473   store::Item_t qname;
1474   GENV_ITEMFACTORY->createQName(qname, strUri, zstring(), lLocal);
1475 
1476 
1477   switch( xsTypeDef->getTypeCategory() )
1478   {
1479   case XSTypeDefinition::SIMPLE_TYPE:
1480     {
1481       xqtref_t xqType = createXQTypeFromTypeDefinition(typeManager, xsTypeDef);
1482       addTypeToCache(xqType);
1483     }
1484     break;
1485 
1486   case XSTypeDefinition::COMPLEX_TYPE:
1487     {
1488       // get content type
1489       XSComplexTypeDefinition* xsComplexTypeDef =
1490         static_cast<XSComplexTypeDefinition*> (xsTypeDef);
1491 
1492       XQType::content_kind_t contentType;
1493 
1494       switch (xsComplexTypeDef->getContentType())
1495       {
1496       case XSComplexTypeDefinition::CONTENTTYPE_MIXED :
1497         contentType = XQType::MIXED_CONTENT_KIND;
1498         break;
1499       case XSComplexTypeDefinition::CONTENTTYPE_ELEMENT :
1500         contentType = XQType::ELEMENT_ONLY_CONTENT_KIND;
1501         break;
1502       case XSComplexTypeDefinition::CONTENTTYPE_SIMPLE :
1503         contentType = XQType::SIMPLE_CONTENT_KIND;
1504         break;
1505       case XSComplexTypeDefinition::CONTENTTYPE_EMPTY :
1506         contentType = XQType::EMPTY_CONTENT_KIND;
1507         break;
1508       default:
1509         ZORBA_ASSERT(false);
1510       }
1511 
1512       xqtref_t xqType =
1513         xqtref_t(new UserDefinedXQType(typeManager,
1514                                        qname,
1515                                        baseXQType,
1516                                        TypeConstants::QUANT_ONE,
1517                                        UserDefinedXQType::COMPLEX_TYPE,
1518                                        contentType));
1519 
1520       addTypeToCache(xqType);
1521 
1522       // check f0r it's containing annonymous types
1523       checkForAnonymousTypesInType(typeManager, xsComplexTypeDef);
1524     }
1525     break;
1526 
1527   default:
1528     // no other known type category
1529     ZORBA_ASSERT(false);
1530   }
1531 }
1532 
1533 
addTypeToCache(xqtref_t itemXQType)1534 void Schema::addTypeToCache(xqtref_t itemXQType)
1535 {
1536   ZORBA_ASSERT( itemXQType->type_kind() == XQType::USER_DEFINED_KIND );
1537 
1538   const UserDefinedXQType* itemUDType =
1539     static_cast<const UserDefinedXQType*>(itemXQType.getp());
1540 
1541   const store::Item* qname = itemUDType->get_qname();
1542 
1543   const zstring& local = qname->getLocalName();
1544   const zstring& ns = qname->getNamespace();
1545 
1546   zstring key;
1547   key.reserve(ns.size() + local.size() + 4);
1548   key += local;
1549   key += ":";
1550   key += ns;
1551   key += " ";
1552   key += TypeOps::decode_quantifier(itemXQType->get_quantifier());
1553 
1554   xqtref_t res;
1555   if( !theUdTypesCache->get(key, res) )
1556   {
1557     TRACE("key: '" << key << "'");
1558     theUdTypesCache->insert(key, itemXQType);
1559   }
1560 }
1561 
1562 #endif //ZORBA_NO_XMLSCHEMA
1563 
1564 
1565 /*******************************************************************************
1566   Parse a given string to create (if possible) an XDM value of a given type.
1567   The given type is assumed to be a simple type, i.e. Atomic, List or Union.
1568 ********************************************************************************/
parseUserSimpleTypes(zstring & textValue,const xqtref_t & aTargetType,std::vector<store::Item_t> & resultList,const QueryLoc & loc)1569 bool Schema::parseUserSimpleTypes(
1570     zstring& textValue,
1571     const xqtref_t& aTargetType,
1572     std::vector<store::Item_t>& resultList,
1573     const QueryLoc& loc)
1574 {
1575   //cout << "parseUserSimpleTypes: '" << textValue << "' to " <<
1576   //  aTargetType->toString() << endl; cout.flush();
1577 
1578   if ( aTargetType->type_kind() != XQType::USER_DEFINED_KIND )
1579   {
1580     // must be a built in type
1581     store::Item_t atomicResult;
1582     //todo add nsCtx
1583     bool res = GenericCast::instance()->castToAtomic(atomicResult,
1584                                                      textValue,
1585                                                      aTargetType,
1586                                                      theTypeManager,
1587                                                      NULL,
1588                                                      loc);
1589 
1590     if ( res == false )
1591     {
1592       return false;
1593     }
1594     else
1595     {
1596       // use resultList.resize() and resultList[x].transfer(atomicResult)
1597       //resultList.push_back(atomicResult);
1598       std::size_t s = resultList.size();
1599       resultList.resize(s+1);
1600       resultList[s].transfer(atomicResult);
1601 
1602       return true;
1603     }
1604   }
1605 
1606   const UserDefinedXQType* udXQType =
1607     static_cast<const UserDefinedXQType*>(aTargetType.getp());
1608 
1609   ZORBA_ASSERT(udXQType->isAtomic() || udXQType->isList() || udXQType->isUnion());
1610 
1611   bool hasResult = false;
1612 
1613   switch ( udXQType->getTypeCategory() )
1614   {
1615   case UserDefinedXQType::ATOMIC_TYPE:
1616   {
1617     store::Item_t atomicResult;
1618     hasResult = parseUserAtomicTypes(textValue, aTargetType, atomicResult, NULL, loc);
1619 
1620     if ( !hasResult )
1621       return false;
1622     else
1623     {
1624       //resultList.push_back(atomicResult);
1625       std::size_t s = resultList.size();
1626       resultList.resize(s+1);
1627       resultList[s].transfer(atomicResult);
1628       return true;
1629     }
1630   }
1631   break;
1632 
1633   case UserDefinedXQType::LIST_TYPE:
1634     return parseUserListTypes(textValue, aTargetType, resultList, loc);
1635     break;
1636 
1637   case UserDefinedXQType::UNION_TYPE:
1638     return parseUserUnionTypes(textValue, aTargetType, resultList, loc);
1639     break;
1640 
1641   case UserDefinedXQType::COMPLEX_TYPE:
1642   default:
1643     ZORBA_ASSERT( false);
1644     break;
1645   }
1646 
1647   return false;
1648 }
1649 
1650 
1651 /*******************************************************************************
1652   Parse a given string to create (if possible) an XDM value of a given type.
1653   The given type is assumed to be a user-defined atomic type.
1654 ********************************************************************************/
parseUserAtomicTypes(zstring & textValue,const xqtref_t & aTargetType,store::Item_t & result,namespace_context * aNCtx,const QueryLoc & loc)1655 bool Schema::parseUserAtomicTypes(
1656     zstring& textValue,
1657     const xqtref_t& aTargetType,
1658     store::Item_t& result,
1659     namespace_context* aNCtx,
1660     const QueryLoc& loc)
1661 {
1662   TRACE("parsing '" << textValue << "' to " << aTargetType->toString());
1663 
1664   ZORBA_ASSERT( aTargetType->type_kind() == XQType::USER_DEFINED_KIND );
1665 
1666   const UserDefinedXQType* udXQType =
1667     static_cast<const UserDefinedXQType*>(aTargetType.getp());
1668   ZORBA_ASSERT( udXQType->isAtomic() );
1669 
1670   const store::Item* typeQName = udXQType->get_qname();
1671 
1672 #ifndef ZORBA_NO_XMLSCHEMA
1673   XMLChArray localPart (typeQName->getLocalName());
1674   XMLChArray uriStr (typeQName->getNamespace());
1675 
1676   bool wasError = false;
1677 
1678   try
1679   {
1680     // Create grammar resolver and string pool that we pass to the scanner
1681     std::auto_ptr<GrammarResolver> fGrammarResolver(
1682         new GrammarResolver(theGrammarPool));
1683 
1684     fGrammarResolver->useCachedGrammarInParse(true);
1685 
1686     // retrieve Grammar for the uri
1687     SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uriStr);
1688 
1689     if (sGrammar)
1690     {
1691       DatatypeValidator* xsiTypeDV = fGrammarResolver->
1692           getDatatypeValidator(uriStr, localPart);
1693 
1694       if (!xsiTypeDV)
1695       {
1696         // when complex simple content type use the base type
1697         // find the first basetype that has a DataTypeValidator
1698         const UserDefinedXQType* tmpXQType = udXQType;
1699 
1700         while (xsiTypeDV == NULL && tmpXQType != NULL)
1701         {
1702           xqtref_t baseXQType = tmpXQType->getBaseType();
1703           if (baseXQType.getp())
1704           {
1705             store::Item_t baseTypeQName = baseXQType->get_qname();
1706             XMLChArray baseLocalPart(baseTypeQName->getLocalName());
1707             XMLChArray baseUriStr(baseTypeQName->getNamespace());
1708 
1709             xsiTypeDV = fGrammarResolver->
1710               getDatatypeValidator(baseUriStr, baseLocalPart);
1711 
1712             tmpXQType = NULL;
1713             if (baseXQType->type_kind() == XQType::USER_DEFINED_KIND)
1714             {
1715               tmpXQType =
1716                 static_cast<const UserDefinedXQType*>(baseXQType.getp());
1717             }
1718           }
1719         }
1720       }
1721 
1722       if (!xsiTypeDV)
1723       {
1724         throw XQUERY_EXCEPTION(
1725           err::FORG0001, ERROR_PARAMS( aTargetType, ZED( NoTypeInCtx ) )
1726         );
1727       }
1728 
1729       // workaround for validating xs:NOTATION with Xerces
1730       if (theTypeManager != NULL
1731           &&
1732           udXQType->isSubTypeOf(theTypeManager, *GENV_TYPESYSTEM.NOTATION_TYPE_ONE))
1733       {
1734         // textValue must be in the form of URI:LOCAL
1735         size_t colonIndex = textValue.find_first_of(":");
1736         zstring prefix = textValue.substr(0, colonIndex).str();
1737         zstring local = textValue.substr(colonIndex+1, textValue.size()).str();
1738         zstring uri;
1739 
1740         if (aNCtx != NULL && aNCtx->findBinding(prefix, uri))
1741         {
1742           XMLChArray xchTextValue(uri.append(":").append(local).str());
1743           xsiTypeDV->validate(xchTextValue.get());
1744         }
1745         else
1746           ZORBA_ERROR_DESC_OSS(err::FORG0001, "Prefix '" << prefix <<
1747               "' not found in current namespace context.");
1748       }
1749       else
1750       {
1751         XMLChArray xchTextValue(textValue.str());
1752         xsiTypeDV->validate(xchTextValue.get());
1753       }
1754     }
1755     else
1756     {
1757       ZORBA_ERROR_DESC_OSS(err::FORG0001,
1758                            "Uri '" << typeQName->getNamespace()
1759                            << "' not found in current schema context.");
1760       wasError = true;
1761     }
1762 
1763     if (wasError)
1764       return false;
1765   }
1766   catch (XMLException& idve)
1767   {
1768     zstring msg;
1769     transcode(idve.getMessage(), msg);
1770 
1771     throw XQUERY_EXCEPTION(
1772       err::FORG0001,
1773       ERROR_PARAMS( textValue, ZED( NoCastTo_34o ), aTargetType, msg )
1774     );
1775   }
1776   catch(const OutOfMemoryException&)
1777   {
1778     throw;
1779   }
1780   catch (const ZorbaException&)
1781   {
1782     throw;
1783   }
1784   catch (...)
1785   {
1786     throw;
1787   }
1788 #endif //ZORBA_NO_XMLSCHEMA
1789 
1790   // find the non user defined base type
1791   const XQType* baseType = udXQType->getBaseType().getp();
1792 
1793   while (baseType->type_kind() == XQType::USER_DEFINED_KIND)
1794   {
1795     const UserDefinedXQType* udt =
1796         static_cast<const UserDefinedXQType*>(baseType);
1797 
1798     baseType = udt->getBaseType().getp();
1799   }
1800 
1801   // create a UserTypedAtomicItem with the built-in value
1802   store::Item_t baseItem;
1803 
1804   if (GenericCast::castToAtomic(baseItem,
1805                                 textValue,
1806                                 baseType,
1807                                 theTypeManager,
1808                                 aNCtx,
1809                                 loc))
1810   {
1811     store::Item_t tTypeQName = udXQType->get_qname();
1812 
1813     //TRACE("factory '" << baseItem->getStringValue() << "' type " << tTypeQName->getStringValue() << "  base:" << baseType->toString());
1814     return GENV_ITEMFACTORY->
1815         createUserTypedAtomicItem(result, baseItem, tTypeQName);
1816   }
1817   else
1818     return false;
1819 }
1820 
1821 
splitToAtomicTextValues(const zstring & textValue,std::vector<zstring> & atomicTextValues)1822 void splitToAtomicTextValues(
1823     const zstring& textValue,
1824     std::vector<zstring>& atomicTextValues)
1825 {
1826   zstring normalizedTextValue;
1827   utf8::normalize_whitespace(textValue, &normalizedTextValue);
1828 
1829   size_t start = 0;
1830   size_t i = 0;
1831 
1832   while ( std::string::npos != (i=normalizedTextValue.find_first_of(" \n\r\t", start)) )
1833   {
1834     atomicTextValues.push_back(normalizedTextValue.substr(start, i - start));
1835     start = i+1;
1836   }
1837 
1838   size_t size = normalizedTextValue.size();
1839 
1840   if ( start < size )
1841   {
1842     atomicTextValues.push_back(normalizedTextValue.substr(start, size));
1843   }
1844 }
1845 
1846 
1847 
1848 // user list types
parseUserListTypes(const zstring & textValue,const xqtref_t & aTargetType,std::vector<store::Item_t> & resultList,const QueryLoc & loc)1849 bool Schema::parseUserListTypes(
1850     const zstring& textValue,
1851     const xqtref_t& aTargetType,
1852     std::vector<store::Item_t>& resultList,
1853     const QueryLoc& loc)
1854 {
1855   ZORBA_ASSERT( aTargetType->type_kind() == XQType::USER_DEFINED_KIND );
1856 
1857 //  cout << "parseUserListTypes: '" << textValue << "' to " <<
1858 //    aTargetType->toString() << endl; cout.flush();
1859 
1860   const UserDefinedXQType* udXQType =
1861     static_cast<const UserDefinedXQType*>(aTargetType.getp());
1862   ZORBA_ASSERT( udXQType->isList() );
1863 
1864   bool hasResult = true;
1865   const XQType* listItemType = udXQType->getListItemType();
1866   ZORBA_ASSERT( listItemType );
1867 
1868   //split text into atoms
1869   std::vector<zstring> atomicTextValues;
1870   splitToAtomicTextValues(textValue, atomicTextValues);
1871 
1872   for ( unsigned int i = 0; i < atomicTextValues.size() ; i++)
1873   {
1874     TRACE("trying parsing '" << textValue << "' to " <<
1875         listItemType->toString());
1876 
1877     bool res = parseUserSimpleTypes(atomicTextValues[i],
1878                                     xqtref_t(listItemType),
1879                                     resultList,
1880                                     loc);
1881     hasResult = hasResult && res;
1882   }
1883 
1884   return hasResult;
1885 }
1886 
1887 // user union types
parseUserUnionTypes(zstring & textValue,const xqtref_t & aTargetType,std::vector<store::Item_t> & resultList,const QueryLoc & loc)1888 bool Schema::parseUserUnionTypes(
1889     zstring& textValue,
1890     const xqtref_t& aTargetType,
1891     std::vector<store::Item_t>& resultList,
1892     const QueryLoc& loc)
1893 {
1894 //  cout << "parseUserUnionTypes: '" << textValue << "'" <<  " to " <<
1895 //    aTargetType->toString() << endl; cout.flush();
1896 
1897   ZORBA_ASSERT( aTargetType->type_kind() == XQType::USER_DEFINED_KIND );
1898 
1899   const UserDefinedXQType* udXQType =
1900   static_cast<const UserDefinedXQType*>(aTargetType.getp());
1901   ZORBA_ASSERT( udXQType->isUnion() );
1902 
1903   std::vector<xqtref_t> unionItemTypes = udXQType->getUnionItemTypes();
1904 
1905   for ( unsigned int i = 0; i < unionItemTypes.size(); i++)
1906   {
1907     try
1908     {
1909       if (isCastableUserSimpleTypes(textValue, unionItemTypes[i]))
1910       {
1911         return parseUserSimpleTypes(textValue, unionItemTypes[i], resultList, loc);
1912       }
1913     }
1914     catch(ZorbaException const&)
1915     {
1916     }
1917   }
1918 
1919   throw XQUERY_EXCEPTION(
1920     err::FORG0001,
1921     ERROR_PARAMS( textValue, ZED( NoCastTo_34o ), udXQType->toSchemaString() )
1922   );
1923 }
1924 
1925 
1926 // user defined simple types, i.e. Atomic, List or Union Types
isCastableUserSimpleTypes(const zstring & textValue,const xqtref_t & aTargetType)1927 bool Schema::isCastableUserSimpleTypes(
1928     const zstring& textValue,
1929     const xqtref_t& aTargetType)
1930 {
1931   //cout << "isCastableUserSimpleTypes: '" << textValue << "' to " <<
1932   //  aTargetType->toString() << endl; cout.flush();
1933 
1934   if ( aTargetType->type_kind() != XQType::USER_DEFINED_KIND )
1935   {
1936     // must be a built in type
1937     store::Item_t atomicResult;
1938 
1939     return GenericCast::instance()->isCastable(textValue, aTargetType, theTypeManager);
1940     //todo add nsCtx
1941   }
1942 
1943   ZORBA_ASSERT( aTargetType->type_kind() == XQType::USER_DEFINED_KIND );
1944 
1945   const UserDefinedXQType* udXQType =
1946     static_cast<const UserDefinedXQType*>(aTargetType.getp());
1947 
1948   ZORBA_ASSERT( udXQType->isAtomic() || udXQType->isList() ||
1949                 udXQType->isUnion() );
1950 
1951 
1952   switch ( udXQType->getTypeCategory() )
1953   {
1954   case UserDefinedXQType::ATOMIC_TYPE:
1955     return isCastableUserAtomicTypes( textValue, aTargetType );
1956     break;
1957 
1958   case UserDefinedXQType::LIST_TYPE:
1959     return isCastableUserListTypes( textValue, aTargetType );
1960     break;
1961 
1962   case UserDefinedXQType::UNION_TYPE:
1963     return isCastableUserUnionTypes( textValue, aTargetType );
1964     break;
1965 
1966   case UserDefinedXQType::COMPLEX_TYPE:
1967   default:
1968     ZORBA_ASSERT( false);
1969     break;
1970   }
1971 
1972   return false;;
1973 }
1974 
1975 
1976 // user defined atomic types
isCastableUserAtomicTypes(const zstring & textValue,const xqtref_t & aTargetType)1977 bool Schema::isCastableUserAtomicTypes(
1978     const zstring& textValue,
1979     const xqtref_t& aTargetType)
1980 {
1981   //cout << "isCastableUserAtomicTypes: '" << textValue << "' to " <<
1982   //  aTargetType->toString() << endl; cout.flush();
1983   return GenericCast::instance()->isCastable(textValue, aTargetType.getp(), theTypeManager);
1984 }
1985 
1986 
1987 // user defined list types
isCastableUserListTypes(const zstring & textValue,const xqtref_t & aTargetType)1988 bool Schema::isCastableUserListTypes(
1989     const zstring& textValue,
1990     const xqtref_t& aTargetType)
1991 {
1992   //cout << "isCastableUserListTypes: '" << textValue << "' to " <<
1993   //  aTargetType->toString() << endl; cout.flush();
1994   ZORBA_ASSERT( aTargetType->type_kind() == XQType::USER_DEFINED_KIND );
1995 
1996   const UserDefinedXQType* udXQType =
1997     static_cast<const UserDefinedXQType*>(aTargetType.getp());
1998   ZORBA_ASSERT( udXQType->isList() );
1999 
2000   bool hasResult = true;
2001   const XQType* listItemType = udXQType->getListItemType();
2002 
2003   //split text into atoms
2004   std::vector<zstring> atomicTextValues;
2005   splitToAtomicTextValues(textValue, atomicTextValues);
2006 
2007   for ( unsigned int i = 0; i<atomicTextValues.size() ; i++ )
2008   {
2009     bool res = isCastableUserSimpleTypes(atomicTextValues[i],
2010                                          xqtref_t(listItemType));
2011     hasResult = hasResult && res;
2012   }
2013 
2014   return hasResult;
2015 }
2016 
2017 
2018 // user defined union types
isCastableUserUnionTypes(const zstring & textValue,const xqtref_t & aTargetType)2019 bool Schema::isCastableUserUnionTypes(
2020     const zstring& textValue,
2021     const xqtref_t& aTargetType)
2022 {
2023     //cout << "isCastableUserUnionTypes: '" << textValue << "' to " <<
2024     //  aTargetType->toString() << endl; cout.flush();
2025 
2026     ZORBA_ASSERT( aTargetType->type_kind() == XQType::USER_DEFINED_KIND );
2027 
2028     const UserDefinedXQType* udXQType =
2029       static_cast<const UserDefinedXQType*>(aTargetType.getp());
2030     ZORBA_ASSERT( udXQType->isUnion() );
2031 
2032 
2033     std::vector<xqtref_t> unionItemTypes = udXQType->getUnionItemTypes();
2034 
2035     for ( unsigned int i = 0; i<unionItemTypes.size(); i++)
2036     {
2037       if ( isCastableUserSimpleTypes(textValue, unionItemTypes[i]))
2038         return true;
2039     }
2040 
2041     return false;
2042 }
2043 
serialize(::zorba::serialization::Archiver & ar)2044 void Schema::serialize(::zorba::serialization::Archiver& ar)
2045 {
2046   SERIALIZE_TYPEMANAGER(TypeManager, theTypeManager);
2047 
2048 #ifndef ZORBA_NO_XMLSCHEMA
2049    ar & theUdTypesCache;
2050 
2051    bool is_grammar_NULL = (theGrammarPool == NULL);
2052 
2053    ar.set_is_temp_field(true);
2054 
2055    ar & is_grammar_NULL;
2056 
2057    csize size_of_size_t = sizeof(size_t);
2058 
2059    union
2060    {
2061      unsigned long lvalue;
2062      unsigned char cvalue[4];
2063    } le_be_value;
2064 
2065    le_be_value.lvalue = 0x11223344;
2066 
2067    if (ar.is_serializing_out())
2068    {
2069      ar & size_of_size_t;
2070      ar & le_be_value.cvalue[0];
2071 
2072      if (!is_grammar_NULL)
2073      {
2074        BinMemOutputStream binmemoutputstream;
2075        zstring binstr;
2076 
2077        try
2078        {
2079          theGrammarPool->serializeGrammars(&binmemoutputstream);
2080          binstr.assign((char*)binmemoutputstream.getRawBuffer(),
2081                        binmemoutputstream.getSize());
2082        }
2083        catch (...)
2084        {
2085        }
2086 
2087        ar & binstr;
2088      }
2089    }
2090    else
2091    {
2092      csize size_of_size_t2;
2093      unsigned char le_be_value_first_char;
2094 
2095      ar & size_of_size_t2;
2096      ar & le_be_value_first_char;
2097 
2098      if (size_of_size_t2 != size_of_size_t ||
2099          le_be_value_first_char != le_be_value.cvalue[0])
2100      {
2101        throw ZORBA_EXCEPTION(zerr::ZCSE0015_INCOMPATIBLE_BETWEEN_32_AND_64_BITS_OR_LE_AND_BE);
2102      }
2103 
2104      if (!is_grammar_NULL)
2105      {
2106        zstring binstr;
2107 
2108        ar & binstr;
2109 
2110        if (!binstr.empty())
2111        {
2112          BinMemInputStream binmeminputstream((XMLByte*)binstr.c_str(), binstr.size());
2113          theGrammarPool->deserializeGrammars(&binmeminputstream);
2114        }
2115      }
2116      else
2117      {
2118        theGrammarPool = NULL;
2119      }
2120    }
2121 
2122    ar.set_is_temp_field(false);
2123 #endif
2124 }
2125 
2126 } // namespace zorba
2127 /* vim:set et sw=2 ts=2: */
2128