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