wsdlpull  1.23
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
SchemaParser.cpp
Go to the documentation of this file.
1 /*
2  * wsdlpull - A C++ parser for WSDL (Web services description language)
3  * Copyright (C) 2005-2007 Vivek Krishna
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  *
19  */
20 
22 
23 #ifndef _WIN32
24 #include "xmlpull/ConfigFile.h"
25 #endif
26 
27 //
28 #include <climits>
29 
30 namespace Schema {
31 using namespace std;
33  std::string tns,
34  std::ostream & log,
35  const std::string & s)
36  :tnsUri_(tns),
37  xParser_(parser),
38  elementQualified_ (false),
39  attributeQualified_ (false),
40  deleteXmlParser_(false),
41  resolveFwdRefs_(true),
42  level_(1),
43  logFile_(log),
44  confPath_(s)
45 {
46  init();
47 }
48 
49 SchemaParser::SchemaParser(const std::string &Uri,
50  std::string tns ,
51  std::ostream & log ,
52  const std::string & s)
53  :tnsUri_(tns),
54  xParser_(0),
55  elementQualified_ (false),
56  attributeQualified_ (false),
57  deleteXmlParser_(false),
58  resolveFwdRefs_(true),
59  level_(1),
60  logFile_(log),
61  confPath_(s)
62 {
63  if(XmlUtils::fetchUri(Uri,fname_))
64  {
65  xmlStream_.open(fname_.c_str());
66  xParser_ = new XmlPullParser(xmlStream_);
67  xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true);
68  xParser_->require(XmlPullParser::START_DOCUMENT, "", "");
69  while (!xmlStream_.fail() && xParser_->getEventType() != xParser_->END_DOCUMENT)
70  {
71  xParser_->nextTag();
72  if (xParser_->getEventType() == xParser_->START_TAG &&
73  xParser_->getName() == "schema")
74  {
75  deleteXmlParser_=true;
76  tnsUri_=tns;
77  break;
78  }
79  }
80 
81  }
82  if(!deleteXmlParser_) //something wron while opening the schema file
83  {
84  delete xParser_;
85  xParser_=0;
86  }
87 
88  init();
89  uri_ = Uri.substr(0,Uri.rfind('/') + 1);
90 }
91 
92 void
93 SchemaParser::init()
94 {
95  lElems_.clear() ;
96  lAttributes_.clear();
97  lAttributeGroups_.clear();
98  importedSchemas_.clear();
99  constraints_.clear();
100 
101  if (confPath_.empty()) {
102 #if defined SCHEMADIR
103  confPath_ = SCHEMADIR;
104 #else
105  confPath_ = "src/schemas";
106 #endif
107  }
108 
109  Element e("schema",
110  SchemaUri,
111  SchemaUri,
113  lElems_.push_back(e);
114 
115 
116 
117 #ifdef LOGGING
118  level_ = 2;
119 #endif
120 }
121 
123 {
124  //clear the Types table
125  typesTable_.clean();
126  if(deleteXmlParser_) {
127 
128  delete xParser_;
129  xmlStream_.close();
130  }
131 
132  for (ConstraintList::iterator ci=constraints_.begin();
133  ci != constraints_.end();
134  ci++)
135  delete *ci;
136  for (AttributeGroupList::iterator agi = lAttributeGroups_.begin();
137  agi != lAttributeGroups_.end();
138  agi++)
139  delete *agi;
140 }
141 
142 
143 /*
144  * Parses an schema definition.
145  * This is the main entry method for the schema parser
146  */
147 bool
149 {
150  int i = 0;
151  try {
152  if(!xParser_)
153  return false;
154  while (xParser_->getEventType() != xParser_->START_TAG)
155  xParser_->next();
156  xParser_->require(xParser_->START_TAG, Schema::SchemaUri, "schema");
157  int attcnt = xParser_->getAttributeCount();
158 
159  //parse the schema tag's attributes
160  for (i = 0; i < attcnt; i++) {
161  std::string attName = xParser_->getAttributeName(i);
162  if ("targetNamespace" == attName)
163  //store the tns URI
164  tnsUri_ = xParser_->getAttributeValue(i);
165  if ("version" == attName)
166  version_ = xParser_->getAttributeValue(i);
167  if ("elementFormDefault" == attName){
168  if (xParser_->getAttributeValue(i) == "unqualified")
169  elementQualified_ = false;
170 
171  else if (xParser_->getAttributeValue(i) == "qualified")
172  elementQualified_ = true;
173  }
174  if ("attributeFormDefault" == attName) {
175  if (xParser_->getAttributeValue(i) == "unqualified")
176  attributeQualified_ = false;
177 
178  else if (xParser_->getAttributeValue(i) == "qualified")
179  attributeQualified_ = true;
180  }
181  }
182 
183  for (i = xParser_->getNamespaceCount(xParser_->getDepth()) - 1;
184  i > xParser_->getNamespaceCount(xParser_->getDepth() - 1) - 1; i--)
185  if (xParser_->getNamespaceUri(i) == tnsUri_)
186  tnsPrefix_ = xParser_->getNamespacePrefix(i);
187  typesTable_.setTargetNamespace(tnsUri_);
188  xParser_->nextTag();
189 
190  return parseSchema();
191  } catch (XmlPullParserException xpe){
192 
193  logFile_ <<"Error parsing schema for namespace "<<tnsUri_<<std::endl;
194  logFile_ << xpe.description << " at "
195  << xpe.line << ":" << xpe.col
196  << std::endl;
197  return false;
198  }
199  catch(SchemaParserException spe) {
200 
201  spe.line = xParser_->getLineNumber();
202  spe.col = xParser_->getColumnNumber();
203 
204  logFile_ << spe.description << " at "
205  << spe.line << ":" << spe.col
206  << std::endl;
207 
208  return false;
209  }
210 }
211 
212 //this function handles the schema
213 bool
214 SchemaParser::parseSchema(std::string tag)
215 {
216  try
217  {
218  do
219  {
220 
221  if (xParser_->getEventType() == xParser_->END_TAG)
222  {
223  if (xParser_->getName() == tag)
224  break;
225  while (xParser_->getEventType() != xParser_->START_TAG)
226  xParser_->nextTag();
227  }
228 
229  /*
230  This is the main loop
231  Depending on the tag encountered call the appropriate routines
232  Schema elements visible at this level
233  1. Global Element declarations
234  2. Global attribute declarations
235  3. Complex type and Simple type declarations
236 
237  */
238  std::string elemName = xParser_->getName();
239  if (elemName == "element") {
240  bool fwd;
241  Element e = parseElement(fwd);
242  lElems_.push_back(e);
243  }
244  else if (elemName == "complexType")
245  {
246  XSDType *t = parseComplexType();
247  typesTable_.addType(t);
248  }
249  else if (elemName == "simpleType")
250  {
251  XSDType *t = parseSimpleType();
252  typesTable_.addType(t);
253  }
254  else if (elemName == "attribute") {
255  bool fwd;
256  lAttributes_.push_back(parseAttribute(fwd));
257  }
258  else if (elemName == "annotation"){
259  parseAnnotation();
260  }
261  else if (elemName == "import") {
262  parseImport();
263  }
264  else if (elemName=="include"){
265  parseInclude();
266  }
267  else if(elemName=="attributeGroup") {
268  AttributeGroup* ag = parseAttributeGroup();
269  if (ag)
270  lAttributeGroups_.push_back(ag);
271 
272  }else if(elemName=="group") {
273 
274  lGroups_.push_back(parseGroup());
275  Group & g=lGroups_.back();
276  //make this grp the owner of the content model
277  g.setContents(g.getContents(),false);
278  }
279  else if( elemName=="key") {
280 
281  constraints_.push_back(parseConstraint(Schema::Key));
282  }
283  else if( elemName=="keyref") {
284  constraints_.push_back(parseConstraint(Schema::Keyref));
285  }
286  else if( elemName=="unique") {
287  constraints_.push_back(parseConstraint(Schema::Unique));
288  }else if (elemName=="redefine"){
289  parseRedefine();
290  }
291  else {
292  error("Unknown element "+ elemName,1);
293  break;
294  }
295  xParser_->nextTag();
296  }
297  while (true);
298  if ((importedSchemas_.size() == 0) &&
299  typesTable_.detectUndefinedTypes()){
300 
301  typesTable_.printUndefinedTypes(logFile_);logFile_.flush();
302  error("Undefined Types in namespace "+tnsUri_);
303  }
304  if(shouldResolve())
305  {
306 
307  resolveForwardElementRefs();
308  resolveForwardAttributeRefs();
309  }
310 
311  }
312  catch(SchemaParserException spe)
313  {
314  spe.line = xParser_->getLineNumber();
315  spe.col = xParser_->getColumnNumber();
316 
317  logFile_ << spe.description << " at "
318  << spe.line << ":" << spe.col
319  << std::endl;
320 
321  return false;
322  }
323  return true;
324 }
325 
326 
327 void SchemaParser::parseAnnotation()
328 {
329 
330  do
331  {
332  xParser_->nextToken();
333  if (xParser_->getEventType() == xParser_->END_TAG
334  && xParser_->getName() == "annotation")
335  break;
336  }
337  while (true);
338 }
339 
340 
341 ComplexType *
342 SchemaParser::parseComplexType()
343 {
344  ComplexType *newType = new ComplexType(tnsUri_);
345  int attcnt = xParser_->getAttributeCount();
346  for (int i = 0; i < attcnt; i++)
347  {
348  if ("name" == xParser_->getAttributeName(i))
349  newType->setName(xParser_->getAttributeValue(i));
350 
351  if ("mixed" == xParser_->getAttributeName(i) &&
352  (xParser_->getAttributeValue(i).empty() ||
353  xParser_->getAttributeValue(i)=="true"))
354 
355  newType->setContentModel(Schema::Mixed);
356  }
357 
358 
359  do
360  {
361  //begin parsing the complex type's children
362  xParser_->nextTag();
363  if (xParser_->getEventType() == xParser_->END_TAG)
364  {
365  if (xParser_->getName() == "complexType")
366  break;
367 
368  //if an end tag is seen proceed till next start tag
369  while (xParser_->getEventType() != xParser_->START_TAG)
370  xParser_->nextTag();
371  }
372  std::string elemName = xParser_->getName();
373 
374 
375  if (elemName == "all"){
376  ContentModel * cm= new ContentModel(Schema::All);
377  newType->setContents(cm);
378  parseContent(cm);
379  }
380  else if (elemName == "sequence"){
381  ContentModel * cm= new ContentModel(Schema::Sequence);
382  newType->setContents(cm);
383  parseContent(cm);
384  }
385  else if (elemName == "choice"){
386  ContentModel * cm= new ContentModel(Schema::Choice);
387  newType->setContents(cm);
388  parseContent(cm);
389  }
390  else if (elemName == "attribute") {
391  bool f=false;
392  Attribute a=parseAttribute(f);
393  newType->addAttribute(a,f);
394  }else if (elemName=="attributeGroup"){
395  parseAttributeGroup(newType);
396  }
397  else if (elemName=="group"){
398  //TODO
399  ContentModel* cm= new ContentModel(Schema::Sequence);
400  newType->setContents(cm);
401  parseGroup(cm);
402  }
403  else if (elemName == "anyAttribute")
404  addAnyAttribute(newType);
405 
406  else if (elemName == "complexContent")
407  parseComplexContent(newType);
408 
409  else if (elemName == "simpleContent")
410  parseSimpleContent(newType);
411 
412  else if (xParser_->getName() == "annotation")
413  parseAnnotation();
414 
415  else
416  error("Unexpected tag: '"+elemName+"' in "+newType->getName() );
417  }
418  while (true);
419  makeListFromSoapArray(newType);
420  return newType;
421 }
422 
423 AttributeGroup*
424 SchemaParser::parseAttributeGroup(ComplexType* cType)
425 {
426  std::string name,ref;
427  ref = xParser_->getAttributeValue("", "ref");
428  if (!ref.empty())
429  {
430  Qname agRef(ref);
431  AttributeGroup *ag= getAttributeGroup(agRef);
432  if(cType && ag){
433 
434  for(list<Attribute>::iterator ai= ag->begin();
435  ai!=ag->end();
436  ai++)
437  cType->addAttribute(*ai);
438  }
439  else if (cType){
440  cType->addAttributeGroupName(ref);
441  }
442  xParser_->nextTag();
443  return ag;
444  }
445 
446  name = xParser_->getAttributeValue("", "name");
447  AttributeGroup *ag = new AttributeGroup(name);
448  xParser_->nextTag();
449  while (xParser_->getName() == "annotation")
450  {
451  parseAnnotation();
452  xParser_->nextTag();
453  }
454  std::string elemName=xParser_->getName();
455  while (!((xParser_->getEventType() == xParser_->END_TAG) &&
456  (elemName == "attributeGroup"))){
457 
458  if(elemName=="attribute"){
459  bool fwd;
460  ag->addAttribute(parseAttribute(fwd));
461  }else if(elemName=="attributeGroup"){
462  AttributeGroup* ag1=parseAttributeGroup();
463  for(list<Attribute>::iterator ai= ag1->begin();
464  ai!=ag1->end();
465  ai++)
466  ag->addAttribute(*ai);
467  }else if(elemName=="anyAttribute"){
468  ag->addAttribute(addAnyAttribute(cType));
469  }
470  xParser_->nextTag();
471  elemName=xParser_->getName();
472  }
473 
474  if(cType){
475 
476  for(list<Attribute>::iterator ai= ag->begin();
477  ai!=ag->end();
478  ai++)
479  cType->addAttribute(*ai);
480  delete ag;//dont store anonymous attribute groups
481  ag = 0;
482  }
483  return ag;
484 }
485 
486 Group
487 SchemaParser::parseGroup(ContentModel* c)
488 {
489  int minimum = 1, maximum = 1;
490  std::string tmp, name,ref;
491 
492  tmp = xParser_->getAttributeValue("", "minOccurs");
493  if (!tmp.empty())
494  minimum = XmlUtils::parseInt(tmp);
495  tmp = xParser_->getAttributeValue("", "maxOccurs");
496  if (!tmp.empty()) {
497  if ("unbounded" == tmp)
498  maximum = UNBOUNDED;
499  else
500  maximum = XmlUtils::parseInt(tmp);
501  }
502  ref = xParser_->getAttributeValue("", "ref");
503  if (!ref.empty()) {
504 
505  Qname gName(ref);
506  xParser_->nextTag();
507  Group* gRef=getGroup(gName);
508  if(gRef){
509  Group g(*gRef);
510  if(c)
511  c->addGroup(g,true);
512  return g;
513  }
514  else{
515  Group g(gName.getLocalName(),minimum,maximum);
516  if(c)
517  c->addGroup(g,true);
518  return g;
519  }
520  }
521 
522  name = xParser_->getAttributeValue("", "name");
523  Group g(name,minimum,maximum);
524  xParser_->nextTag();
525  while (xParser_->getName() == "annotation") {
526  parseAnnotation();
527  xParser_->nextTag();
528  }
529 
530  std::string elemName = xParser_->getName();
531  ContentModel * cm=0;
532  if (elemName == "all"){
533  cm = new ContentModel(Schema::All);
534  }
535  else if (elemName == "sequence"){
536  cm= new ContentModel(Schema::Sequence);
537  }
538  else if (elemName == "choice"){
539  cm= new ContentModel(Schema::Choice);
540  }
541  g.setContents(cm,true);
542  parseContent(cm);
543  xParser_->nextTag();
544 
545  if(c)
546  c->addGroup(g,false);
547  return g;
548 }
549 
550 void
551 SchemaParser::parseContent(ContentModel * cm)
552 {
553  int minimum = 1, maximum = 1;
554  std::string tmp;
555 
556  tmp = xParser_->getAttributeValue("", "minOccurs");
557  if (!tmp.empty())
558  minimum = XmlUtils::parseInt(tmp);
559  tmp = xParser_->getAttributeValue("", "maxOccurs");
560  if (!tmp.empty())
561  {
562  if ("unbounded" == tmp)
563  maximum = UNBOUNDED;
564  else
565  maximum = XmlUtils::parseInt(tmp);
566  }
567  cm->setMin(minimum);
568  cm->setMax(maximum);
569 
570  xParser_->nextTag();
571  while (xParser_->getName() == "annotation")
572  {
573  parseAnnotation();
574  xParser_->nextTag();
575  }
576 
577  while (!((xParser_->getEventType() == xParser_->END_TAG) &&
578  (xParser_->getName() == "choice"
579  || xParser_->getName() == "sequence"
580  || xParser_->getName() == "all")))
581  {
582  if (xParser_->getName() == "element") {
583  bool f=false;
584  Element e =parseElement(f);
585  cm->addElement(e);
586  }else if(cm->getCompositor()!=Schema::All){
587 
588  if (xParser_->getName() == "any")
589  addAny(cm);
590  else if (xParser_->getName() == "choice"){
591  ContentModel * cmc= new ContentModel(Schema::Choice);
592  cm->addContentModel(cmc);
593  parseContent(cmc);
594  }
595  else if (xParser_->getName() == "sequence"){
596  ContentModel * cms= new ContentModel(Schema::Sequence);
597  cm->addContentModel(cms);
598  parseContent(cms);
599  }
600  else if (xParser_->getName() == "group"){
601  parseGroup(cm);
602  }
603  else if(xParser_->getName() == "annotation") {
604  parseAnnotation();
605  }
606  else
607  error("parseContent: Unexpected tag "+xParser_->getName());
608  }else{
609 
610  error("parseContent <all>:Syntax Error");
611  }
612  xParser_->nextTag();
613  }
614 }
615 
616 Element
617 SchemaParser::parseElement(bool & fwdRef)
618 {
619  std::string name, fixedVal, defaultVal,
620  // the namespace of the element is the
621  // namespace of the sp that parsed it!
622  typeNs = tnsUri_,elemNs = tnsUri_;
623  Constraint* c=0;
624  int type_id = 0, minimum = 1, maximum = 1, attcnt;
625  Qname refName;
626  bool qualified = false,nill = false;
627  XSDType *elemType;
628  fwdRef=false;
629  attcnt = xParser_->getAttributeCount();
630  for (int i = 0; i < attcnt; i++)
631  {
632  std::string attName = xParser_->getAttributeName(i);
633  if ("name" == attName)
634  name = xParser_->getAttributeValue(i);
635 
636  else if ("type" == attName)
637  {
638  Qname typeName(xParser_->getAttributeValue(i));
639  if (type_id > 0)
640  error
641  ("<element> : type and ref are mutually exclusive in element decl");
642  typeName.setNamespace(typeNs=xParser_->getNamespace(typeName.getPrefix()));
643  type_id = getTypeId(typeName, true);
644  if (type_id == 0)
645  error("<element>:Could not resolve type " +
646  typeName.getNamespace() + ":" +
647  typeName.getLocalName(),0);
648  }
649 
650  else if ("form" == attName)
651  {
652  if ("qualified" == xParser_->getAttributeValue(i))
653  qualified = true;
654 
655  else if ("unqualified" == xParser_->getAttributeValue(i))
656  qualified = false;
657  else
658  error("<element>:Invalid value for form in element " +
659  name,1);
660  }
661 
662  else if ("ref" == attName)
663  {
664  if (!name.empty())
665  error
666  ("<element>:name and ref are mutually exclusive in element decl");
667  if (type_id > 0)
668  error
669  ("<element>:type and ref are mutually exclusive in element decl");
670  refName = xParser_->getAttributeValue(i);
671  refName.setNamespace(xParser_->getNamespace(refName.getPrefix()));
672  Element *e=0;
673  elemNs = refName.getNamespace();
674 
675  if(refName.getNamespace()==tnsUri_){
676 
677  e = const_cast<Element*>(getElement(refName));
678  if (e)
679  type_id = e->getType();
680  }
681  else{
682  //The referenced element may be in an imported schemaparser
683  int i=checkImport(refName.getNamespace());
684  if(i>=0 && importedSchemas_[i].sParser) {
685 
686  e=const_cast<Element*>(importedSchemas_[i].sParser->getElement(refName));
687  if (e){
688  //if the type is in an imported schema then we must add a local reference to
689  // its type,because the type id as got by e->getType()
690  // is not valid in the current schema context
691  const XSDType* pType = importedSchemas_[i].sParser->getType(e->getType());
692  type_id= typesTable_.addExternalTypeId(e->getName()+"_"+e->getTypeNamespace(),
693  pType);
694  }
695  }
696  }
697 
698  if (e == 0){
699 
700  fwdRef=true;
701  name=refName.getLocalName();
702  lForwardElemRefs_.push_back(refName);
703  //this will be resolved later
704  }
705  else{
706  name = e->getName();
707  qualified = e->isQualified();
708  defaultVal = e->defaultVal();
709  fixedVal = e->fixedVal();
710  typeNs = e->getTypeNamespace();
711  elemNs = e->getNamespace();
712  }
713 
714 #ifdef LOGGING
715  logFile_<<elemNs<<":"<<name<<" -> element reference("<<type_id<<")"<<std::endl;
716 #endif
717 
718  }
719  else if ("minOccurs" == attName){
720  minimum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
721  }
722  else if ("maxOccurs" == attName){
723  if ("unbounded" == xParser_->getAttributeValue(i))
724  maximum = UNBOUNDED;
725  else
726  maximum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
727  if (maximum == -1){ //invalid value for maxOccurs
728  error("<element>:Invalid value for maxOccurs",1);
729  maximum=1;
730  }
731  }
732  else if ("default" == attName){
733  if (fixedVal.empty())
734  defaultVal = xParser_->getAttributeValue(i);
735 
736  else
737  error("<element>:fixed and default cannot occur together");
738  }
739  else if ("fixed" == attName){
740  if (defaultVal.empty())
741  fixedVal = xParser_->getAttributeValue(i);
742 
743  else
744  error("<element>:fixed and default cannot occur together");
745  }
746 
747  else if ("substitutionGroup" == attName) {
748 
749  //do nothing
750  }
751  else if ("nillable" == attName) {
752 
753  //a nillable element need not have a type ,so set it to anyType id if nop type was given
754  nill = true;
755  minimum = 0;
756  }
757  else
758  error("<element>:Unsupported Attribute "+attName ,2) ;
759  }
760 
761  do
762  {
763  xParser_->nextTag();
764  std::string elemName=xParser_->getName();
765  if (xParser_->getEventType() == xParser_->END_TAG) {
766  if (elemName == "element")
767  break;
768 
769  //if an end tag is seen proceed till next start tag
770  while (xParser_->getEventType() != xParser_->START_TAG)
771  xParser_->nextTag();
772  }
773 
774  if (elemName == "complexType"){
775  elemType = parseComplexType();
776  type_id = typesTable_.addType(elemType);
777  typeNs = elemType->getNamespace();
778  }
779  else if (elemName == "simpleType"){
780  elemType = parseSimpleType();
781  type_id = typesTable_.addType(elemType);
782  typeNs = elemType->getNamespace();
783  }
784  else if (elemName == "annotation"){
785  parseAnnotation();
786  }
787  else if( elemName=="key") {
788  if (c)
789  delete c;
790  c=parseConstraint(Schema::Key);
791  }
792  else if( elemName=="keyref") {
793  if (c)
794  delete c;
795  c=parseConstraint(Schema::Keyref);
796  }
797  else if( elemName=="unique") {
798  if (c)
799  delete c;
800  c=parseConstraint(Schema::Unique);
801  }
802  else{
803  error("<element> : syntax error or unkown tag :"+elemName);
804  }
805  }
806  while (true);
807 
808  if (nill && type_id == 0) {
809  type_id = Schema::XSD_ANYTYPE;
810  }
811 
812  constraints_.push_back(c);
813  Element e(name,
814  elemNs,
815  typeNs,
816  type_id,
817  minimum,
818  maximum,
819  qualified,
820  defaultVal,
821  fixedVal);
822  e.addConstraint(c);
823  return e;
824 }
825 
826 Constraint*
827 SchemaParser::parseConstraint(Schema::ConstraintType cstr)
828 {
829  Constraint * c= new Constraint(cstr);
830  c->setName(xParser_->getAttributeValue("","name"));
831 
832  do
833  {
834  xParser_->nextTag();
835  std::string elemName=xParser_->getName();
836  if (xParser_->getEventType() == xParser_->END_TAG) {
837  if (cstr==Schema::Key && elemName == "key" ||
838  cstr==Schema::Keyref && elemName == "keyref" ||
839  cstr==Schema::Unique && elemName == "unique" )
840  break;
841 
842  //if an end tag is seen proceed till next start tag
843  while (xParser_->getEventType() != xParser_->START_TAG)
844  xParser_->nextTag();
845  }
846  if(elemName=="selector"){
847  c->setSelector(xParser_->getAttributeValue("", "xpath"));
848  xParser_->nextTag();
849  }
850  else if(elemName=="field"){
851  c->addField(xParser_->getAttributeValue("", "xpath"));
852  xParser_->nextTag();
853  }
854  }while (true);
855  return c;
856 }
857 
858 
859 Element
860 SchemaParser::addAny(ContentModel* cm)
861 {
862  std::string ns;
863 
864  int type_id = Schema::XSD_ANY, minimum = 1, maximum = 1, attcnt;
865  //note processContents=lax .
866  attcnt = xParser_->getAttributeCount();
867  for (int i = 0; i < attcnt; i++)
868  {
869  std::string attr = xParser_->getAttributeName(i);
870  if ("namespace" == attr)
871  ns = xParser_->getAttributeValue(i);
872 
873  else if ("minOccurs" == attr)
874  minimum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
875 
876  else if ("maxOccurs" == attr)
877  {
878  if ("unbounded" == xParser_->getAttributeValue(i))
879  maximum = UNBOUNDED;
880  else
881  maximum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
882  if (maximum == -1){ //invalid value for maxOccurs
883  error("<element>:Invalid value for maxOccurs",1);
884  maximum=1;
885  }
886  }
887 
888  else if ("processContents" == attr || "id" == attr) {
889 
890  //do nothing
891  }
892  else
893  error("<any>:Unsupported Attribute "+attr,2);
894  }
895 
896  xParser_->nextTag();
897  do
898  {
899  if (xParser_->getEventType() == xParser_->END_TAG)
900  {
901  if (xParser_->getName() == "any")
902  break;
903 
904  }
905  xParser_->nextToken();
906  }while (true);
907 
908 
909  Element e(ns,
910  ns,
911  ns,
912  type_id,
913  minimum,
914  maximum);
915 
916  cm->addElement(e);
917  return e;
918 }
919 
920 
921 Attribute
922 SchemaParser::addAnyAttribute(ComplexType * cType)
923 {
924  std::string ns;
925  int type_id = Schema::XSD_ANY,attcnt;
926  bool qualified = true;
927 
928  //note processContents=lax .
929  attcnt = xParser_->getAttributeCount();
930  for (int i = 0; i < attcnt; i++)
931  {
932  std::string attr = xParser_->getAttributeName(i);
933  if ("namespace" == attr)
934  ns = xParser_->getAttributeValue(i);
935 
936  else if ("processContents" == attr || "id" == attr)
937  {
938 
939  //do nothing
940  }
941  else
942  error("<anyAttribute>:Unsupported Attribute "+attr,1);
943  }
944 
945  Attribute a(ns,
946  type_id,
947  qualified);
948  if(cType)
949  cType->addAttribute(a);
950  xParser_->nextTag();
951  while (xParser_->getName() == "annotation")
952  {
953  parseAnnotation();
954  xParser_->nextTag();
955  }
956  return a;
957 
958 }
959 
960 
961 //This function parses and attribute
962 Attribute
963 SchemaParser::parseAttribute(bool & fwdRef)
964 {
965  std::string name, fixedVal, defaultVal;
966  int type_id = 0, attcnt;
967  bool qualified = false, use = false;
968  fwdRef=false;
969 
970  Qname refAttribute;
971  attcnt = xParser_->getAttributeCount();
972  for (int i = 0; i < attcnt; i++) {
973  std::string attName = xParser_->getAttributeName(i);
974  std::string attNs=xParser_->getAttributeNamespace(i);
975  std::string attVal=xParser_->getAttributeValue(i);
976 
977 
978  if ("name" == attName)
979  name = attVal;
980  else if ("type" == attName) {
981  if (type_id > 0)
982  error("<attribute>:type and ref are mutually exclusive in element decl");
983  Qname typeName(attVal);
984  typeName.setNamespace(xParser_->
985  getNamespace(typeName.getPrefix()));
986  type_id = getTypeId(typeName, true);
987  if (type_id == 0)
988  error("<attribute>:Could not resolve type " +
989  typeName.getNamespace() +
990  ":" +typeName.getLocalName(),1);
991  }
992  else if ("form" == attName) {
993  if ("qualified" == attVal)
994  qualified = true;
995  else
996  qualified = false;
997  }
998  else if ("ref" == attName) {
999  if (!name.empty())
1000  error("<attribute>:name and ref are mutually exclusive in element decl");
1001  if (type_id > 0)
1002  error("<attribute>:type and ref are mutually exclusive in element decl");
1003  refAttribute = attVal;
1004  refAttribute.setNamespace(xParser_->getNamespace(refAttribute.getPrefix()));
1005  Attribute *a =0;
1006  if(refAttribute.getNamespace()==tnsUri_){
1007  a=getAttribute(refAttribute);
1008  }else{
1009  int i=checkImport(refAttribute.getNamespace());
1010  if(i >=0 && importedSchemas_[i].sParser){
1011  a=importedSchemas_[i].sParser->getAttribute(refAttribute);
1012  }
1013  else
1014  a=0;
1015  }
1016 
1017  if (a == 0){
1018  fwdRef = true;
1019  name=refAttribute.getLocalName();
1020  lForwardAttributeRefs_.push_back(refAttribute);
1021  }
1022  else{
1023  name = a->getName();
1024  type_id = a->getType();
1025  qualified = a->isQualified();
1026  if (defaultVal.empty())
1027  defaultVal = a->defaultVal();
1028  if (fixedVal.empty())
1029  fixedVal = a->fixedVal();
1030  }
1031  }
1032  else if ("default" == attName) {
1033  if (fixedVal.empty())
1034  defaultVal = attVal;
1035  else
1036  error
1037  ("<attribute>:fixed and default cannot occur together");
1038  }
1039  else if ("fixed" == attName) {
1040  if (defaultVal.empty())
1041  fixedVal = attVal;
1042  else
1043  error("<attribute>:fixed and default cannot occur together");
1044  }
1045  else if ("use" == attName) {
1046  if (attVal == "required")
1047  use = true;
1048  else
1049  use = false;
1050  }
1051  else {
1052  int n=-1;
1053  if(!attNs.empty() && ((n=checkImport(attNs))!=-1)){
1054  fixedVal=attNs;//hack for non schema attributes
1055  defaultVal=attVal;//store non schema attributes.esp for soapenc:arrayType
1056  }else{
1057  error("<attribute>:Unsupported attribute {"+ attNs+ "}:"+attName,2);
1058  }
1059  }
1060  }
1061  //Now parse the children of the attribute tag viz simpleType
1062  do
1063  {
1064  xParser_->nextTag();
1065  if (xParser_->getEventType() == xParser_->END_TAG)
1066  {
1067  if (xParser_->getName() == "attribute")
1068  break;
1069 
1070  //if an end tag is seen proceed till next start tag
1071  while (xParser_->getEventType() != xParser_->START_TAG)
1072  xParser_->nextTag();
1073  }
1074 
1075  else if (xParser_->getName() == "simpleType")
1076  {
1077  XSDType *elemType = parseSimpleType();
1078 
1079  //create an anonymous type
1080  type_id = typesTable_.addType(elemType);
1081  }
1082 
1083  else if (xParser_->getName() == "annotation")
1084  parseAnnotation();
1085  else
1086  error("<attribute>:Syntax error or unkown tag "+xParser_->getName());
1087  }
1088  while (true);
1089 
1090  Attribute a(name,
1091  type_id,
1092  qualified,
1093  defaultVal,
1094  fixedVal,
1095  use);
1096  return a;
1097 
1098 }
1099 
1100 SimpleType *
1101 SchemaParser::parseSimpleType()
1102 {
1103  SimpleType *st = new SimpleType(tnsUri_);
1104  int basetype_id = 0;
1105  int attcnt;
1106  attcnt = xParser_->getAttributeCount();
1107  for (int i = 0; i < attcnt; i++)
1108  {
1109  if ("name" == xParser_->getAttributeName(i))
1110  st->setName(xParser_->getAttributeValue(i));
1111 
1112  else
1113  error("<simpleType> :" + xParser_->getAttributeName(i) +
1114  ":Unknown/Unsupported attribute ",2);
1115  }
1116 
1117  do
1118  {
1119  xParser_->nextTag();
1120  if (xParser_->getEventType() == xParser_->END_TAG)
1121  {
1122  if (xParser_->getName() == "simpleType")
1123  break;
1124 
1125  //if an end tag is seen proceed till next start tag
1126  while (xParser_->getEventType() != xParser_->START_TAG)
1127  xParser_->nextTag();
1128  }
1129  if (xParser_->getName() == "restriction")
1130  {
1131  attcnt = xParser_->getAttributeCount();
1132  for (int i = 0; i < attcnt; i++)
1133  {
1134  if ("base" == xParser_->getAttributeName(i))
1135  {
1136  Qname typeName(xParser_->getAttributeValue(i));
1137  typeName.setNamespace(xParser_->
1138  getNamespace(typeName.
1139  getPrefix()));
1140  st->setBaseType(basetype_id =
1141  getTypeId(typeName, true));
1142  if (basetype_id == 0)
1143  error("<simpleType>:" +
1144  xParser_->getAttributeValue(i) +
1145  ":Unknown base type ",1);
1146  }
1147  else
1148  error("<simpleType>:" + xParser_->getAttributeName(i) +
1149  ":Unknown/Unsupported attribute for <restriction>",2);
1150  }
1151  parseRestriction(st);
1152  }
1153  else if (xParser_->getName() == "union"){
1154 
1155  std::string members = xParser_->getAttributeValue("", "memberTypes");
1156  size_t s = 0;
1157  while(s < members.length()){
1158  while(members[s]==' ')s++;
1159  std::string type = members.substr(s,members.find(' ',s)-s);
1160  Qname typeName(type);
1161  typeName.setNamespace(xParser_->getNamespace(typeName.getPrefix()));
1162  basetype_id = getTypeId(typeName,true);
1163  st->setUnionType(basetype_id);
1164  s+=type.length()+1;
1165  }
1166 
1167  xParser_->nextTag();
1168  while(xParser_->getName() == "simpleType"){
1169  XSDType * t = parseSimpleType();
1170  Schema::Type i = (Schema::Type)typesTable_.addType(t);
1171 
1172  st->setUnionType(i);
1173  xParser_->nextTag();
1174  }
1175  }
1176  else if(xParser_->getName() == "list"){
1177 
1178  basetype_id = getTypeId(xParser_->getAttributeValue("", "itemType"));
1179  st->setListType(basetype_id);
1180  xParser_->nextTag();
1181  }
1182  else if (xParser_->getName() == "annotation")
1183  parseAnnotation();
1184  else
1185  error("<simpleType>:Syntax error");
1186  }
1187  while (true);
1188  return st;
1189 }
1190 
1191 void
1192 SchemaParser::parseRestriction(SimpleType * st,
1193  ComplexType * ct)
1194 {
1195  if (st->getBaseTypeId() == 0)
1196  error("<restriction>:unkown BaseType",1);
1197 
1198  do {
1199  xParser_->nextTag();
1200  if (xParser_->getEventType() == xParser_->END_TAG)
1201  {
1202  if (xParser_->getName() == "restriction")
1203  break;
1204  else
1205  xParser_->nextTag();
1206  if (xParser_->getName() == "restriction"
1207  && xParser_->getEventType() == xParser_->END_TAG)
1208  break;
1209  }
1210  while (xParser_->getName() == "annotation") {
1211  parseAnnotation();
1212  xParser_->nextTag();
1213  }
1214  if(xParser_->getName()=="attribute" && ct!=0){
1215  bool f=false;
1216  Attribute a=parseAttribute(f);
1217  ct->addAttribute(a,f);
1218  }
1219  else if (st->isvalidFacet(xParser_->getName())){
1220  //This function also sets the facet if valid
1221 
1222  st->setFacetValue(xParser_->getName(),
1223  xParser_->getAttributeValue("", "value"));
1224  }else{
1225  error("<restriction>:" + xParser_->getName() +
1226  " is not a valid facet /attribute for the type",1);
1227  }
1228  } while (true);
1229 }
1230 
1231 void
1232 SchemaParser::parseComplexContent(ComplexType * ct)
1233 {
1234  int attcnt = xParser_->getAttributeCount();
1235  int i = 0;
1236  Qname typeName;
1237 
1238  ct->setContentModel(Schema::Complex);
1239  xParser_->nextTag();
1240 
1241  while (xParser_->getName() == "annotation") {
1242  parseAnnotation();
1243  xParser_->nextTag();
1244  }
1245 
1246  if (xParser_->getName() == "restriction") {
1247  attcnt = xParser_->getAttributeCount();
1248  for (i = 0; i < attcnt; i++) {
1249  if ("base" == xParser_->getAttributeName(i))
1250  {
1251  typeName = xParser_->getAttributeValue(i);
1252  typeName.setNamespace(xParser_->
1253  getNamespace(typeName.getPrefix()));
1254  }
1255  }
1256  ct->setBaseType(getTypeId(typeName, true),
1258  }
1259  else if (xParser_->getName() == "extension") {
1260  attcnt = xParser_->getAttributeCount();
1261  for (i = 0; i < attcnt; i++) {
1262  if ("base" == xParser_->getAttributeName(i)) {
1263  typeName = xParser_->getAttributeValue(i);
1264  typeName.setNamespace(xParser_->
1265  getNamespace(typeName.getPrefix()));
1266  }
1267  }
1268  ct->setBaseType(getTypeId(typeName, true),
1270  }
1271 
1272  xParser_->nextTag();
1273  while (xParser_->getName() == "annotation") {
1274  parseAnnotation();
1275  xParser_->nextTag();
1276  }
1277 
1278  {
1279  std::string elemName=xParser_->getName();
1280  ContentModel * cm=0;
1281  if (elemName == "all"){
1282  cm= new ContentModel(Schema::All);
1283  }
1284  else if (elemName == "sequence"){
1285  cm= new ContentModel(Schema::Sequence);
1286  }
1287  else if (elemName == "choice"){
1288  cm= new ContentModel(Schema::Choice);
1289  }
1290 
1291  if(cm){
1292  parseContent(cm);
1293  ct->setContents(cm);
1294  xParser_->nextTag();
1295  }
1296 
1297  //parse any attributes
1298  while (xParser_->getEventType() != xParser_->END_TAG){
1299 
1300  if (xParser_->getName() == "attribute") {
1301  bool f=false;
1302  Attribute a=parseAttribute(f);
1303  ct->addAttribute(a,f);
1304  }
1305  else if(xParser_->getName() == "attributeGroup")
1306  {
1307  parseAttributeGroup(ct);
1308 
1309  }
1310  else if (xParser_->getName() == "anyAttribute")
1311  addAnyAttribute(ct);
1312 
1313  xParser_->nextTag();
1314  }
1315  }
1316 
1317  do {
1318  if (xParser_->getEventType() == xParser_->END_TAG)
1319  if ((xParser_->getName() == "restriction" ||
1320  xParser_->getName() == "extension") )
1321  break;
1322  xParser_->nextTag();
1323  }
1324  while (true);
1325 
1326  xParser_->nextTag();
1327 }
1328 
1329 
1330 void
1331 SchemaParser::parseSimpleContent(ComplexType * ct)
1332 {
1333  ct->setContentModel(Schema::Simple);
1334  xParser_->nextTag();
1335  if (xParser_->getName() == "restriction")
1336  {
1337  SimpleType *st = new SimpleType(tnsUri_);
1338  int attcnt = xParser_->getAttributeCount();
1339  int basetype_id = 0;
1340  for (int i = 0; i < attcnt; i++)
1341  {
1342  if ("base" == xParser_->getAttributeName(i))
1343  {
1344  Qname typeName(xParser_->getAttributeValue(i));
1345  typeName.setNamespace(xParser_->
1346  getNamespace(typeName.getPrefix()));
1347  st->setBaseType(basetype_id = getTypeId(typeName, true));
1348  if (basetype_id == 0)
1349  error("<simpleContent> :" +
1350  xParser_->getAttributeValue(i) +
1351  ":Unknown base type ",1);
1352  }
1353 
1354  else
1355  error("<simpleContent> :" + xParser_->getAttributeName(i) +
1356  ":Unknown/Unsupported attribute ",2);
1357  }
1358  parseRestriction(st,ct);
1359  int typeId = typesTable_.addType(st);
1360  ct->setSimpleContentType(typeId);
1361  }
1362 
1363  else if (xParser_->getName() == "extension")
1364  {
1365  //This extension does not use the full model that can come in
1366  //ComplexContent .It uses the simple model.no particle allowed ,only attributes
1367  int attcnt = xParser_->getAttributeCount();
1368  int basetype_id = 0;
1369  for (int i = 0; i < attcnt; i++)
1370  {
1371  if ("base" == xParser_->getAttributeName(i))
1372  {
1373  Qname typeName(xParser_->getAttributeValue(i));
1374  typeName.setNamespace(xParser_->
1375  getNamespace(typeName.getPrefix()));
1376  ct->setSimpleContentType(basetype_id =
1377  getTypeId(typeName, true));
1378  if (basetype_id == 0)
1379  error("<simpleContent> :" +
1380  xParser_->getAttributeValue(i) +
1381  ":Unknown base type ",1);
1382  }
1383 
1384  else
1385  error("<simpleContent> :" + xParser_->getAttributeName(i) +
1386  ":Unknown/Unsupported attribute ");
1387  }
1388  xParser_->nextTag();
1389  do
1390  {
1391 
1392  if (xParser_->getName() == "attribute")
1393  {
1394  bool f=false;
1395  Attribute a=parseAttribute(f);
1396  ct->addAttribute(a,f);
1397 
1398 
1399  }
1400  else if(xParser_->getName() == "attributeGroup")
1401  {
1402  parseAttributeGroup(ct);
1403 
1404  }
1405 
1406  else if (xParser_->getName() == "anyAttribute")
1407  addAnyAttribute(ct);
1408  else
1409  break;
1410  xParser_->nextTag();
1411  }while(true);
1412 
1413  if (!
1414  (xParser_->getName() == "extension"
1415  && xParser_->getEventType() == xParser_->END_TAG))
1416  error("<simpleContent> :Syntax error :extension");
1417  }
1418  xParser_->nextTag();
1419  if (!
1420  (xParser_->getName() == "simpleContent"
1421  && xParser_->getEventType() == xParser_->END_TAG))
1422  error("<simpleContent> :Syntax error ");
1423 }
1424 
1425 
1426 bool
1427 SchemaParser::parseRedefine()
1428 {
1429  parseInclude();
1430  resolveFwdRefs_=false;
1431  parseSchema("redefine");
1432  resolveFwdRefs_=true;
1433  return true;
1434 }
1435 
1436 bool
1437 SchemaParser::parseInclude()
1438 {
1439  ifstream xsdStream;
1440  std::string loc = xParser_->getAttributeValue("", "schemaLocation");
1441 
1442 
1443  // FV Sat Dec 22 15:33:09 CET 2007 I added the absolute path and the file:/ use-cases
1444  //in the the test. Will not work for paths like "C:\temp\schema.xsd" .Use the file:/ protocol
1445 
1446 
1447  if ( loc.find("/",0) != 0 && // not an asolute path
1448  loc.find("file:/",0) == std::string::npos &&
1449  loc.find("http://") == std::string::npos)
1450  loc = uri_ + loc;
1451 
1452 
1453 #ifndef _WIN32
1454 
1455  if (!loc.empty()) {
1456 
1457  std::string schemaconf= confPath_ + "schema.conf";
1458  try {
1459  ConfigFile cf(schemaconf);
1460  cf.readInto<std::string>(loc,loc);
1461  }catch (const ConfigFile::file_not_found & e) {}
1462  }
1463 #endif
1464 
1465 
1466  if(!loc.empty())
1467  {
1468  if(XmlUtils::fetchUri(loc,fname_))
1469  {
1470  /*
1471  * If the schema definition was retrieved successfully
1472  * process it and add all type definitions and
1473  * declaration to the current namespace
1474  */
1475  xsdStream.open(fname_.c_str());
1476 
1477  XmlPullParser * xpp = new XmlPullParser(xsdStream);
1478  XmlPullParser * tmpXparser=xParser_;
1479  xParser_=xpp;
1480 
1481  xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true);
1482  xParser_->require(XmlPullParser::START_DOCUMENT, "", "");
1483  while (xParser_->getEventType() != xParser_->END_DOCUMENT){
1484  xParser_->nextTag();
1485  if (xParser_->getEventType() == xParser_->START_TAG &&
1486  xParser_->getName() == "schema"){
1487  resolveFwdRefs_=false;
1488 
1489  if(!parseSchemaTag())
1490  error("Error while parsing the included schema " + loc);
1491  else{
1492 
1493  resolveFwdRefs_=true;
1494  break;
1495  }
1496  }
1497  }
1498  xParser_=tmpXparser;
1499  delete xpp;
1500  }
1501  else{
1502 
1503  error("Error while opening the included schema " + loc);
1504  }
1505  }
1506  else{
1507 
1508  error("schemaLocation is a required attribute for <include>");
1509  }
1510 
1511  xParser_->nextTag();
1512  return true;
1513 }
1514 
1515 bool
1516 SchemaParser::parseImport()
1517 {
1518  Qname typeName;
1519  std::string xsdFile;
1520  std::string ns = xParser_->getAttributeValue("", "namespace");
1521  std::string loc=xParser_->getAttributeValue("", "schemaLocation");
1522 
1523  if(ns == tnsUri_)
1524  return parseInclude();//sometimes import is used to import schemas in same ns.
1525  //treat it internally like include
1526 
1527  // if (loc.empty())
1528  // loc = ns; //try using the namespace as schemalocation
1529 
1530  // FV Sat Dec 22 15:33:09 CET 2007 I added the absolute path and the file:/ use-cases in the the test
1531 // if ( !loc.empty() && loc.find("http://") == std::string::npos)
1532 // loc = uri_ + loc;
1533 
1534  if ( !loc.empty() &&
1535  loc.find("/",0) != 0 && // no an asolute path
1536  loc.find("file:/",0) == std::string::npos &&
1537  loc.find("http://") == std::string::npos)
1538  loc = uri_ + loc;
1539 
1540 #ifndef _WIN32
1541  if (!loc.empty()) {
1542 
1543  std::string schemaconf= confPath_ + "schema.conf";
1544  try {
1545  ConfigFile cf(schemaconf);
1546  cf.readInto<std::string>(loc,loc);
1547  }catch (const ConfigFile::file_not_found &e) {}
1548  }
1549 #endif
1550 
1551  if(!loc.empty())
1552  {
1553  if(XmlUtils::fetchUri(loc,xsdFile))
1554  {
1555  /*
1556  * If the schema definition was retrieved successfully
1557  * process it and add it to list of imported schemas
1558  */
1559  SchemaParser *sp = new SchemaParser(xsdFile,ns);
1560  sp->setUri(uri_);
1561  //pass the imports to the new schema parser
1562  for (size_t i = 0; i < importedSchemas_.size(); i++) {
1563 
1564  if(importedSchemas_[i].sParser ) {
1565  sp->addImport(importedSchemas_[i].sParser);
1566  }
1567  }
1568 
1569  if(sp->parseSchemaTag())
1570  addImport(sp);
1571  else
1572  error("Error while parsing imported namespace "+ns,0);
1573 
1574  }
1575  else{
1576 
1577  error("could not import namespace from location "+loc);
1578  }
1579  }
1580  else{
1581  // if no location is mentioned ,just add the namespace,types will be resolved later
1582 
1583  addImport(ns);
1584  }
1585 
1586  error("Imported namespace "+ns+" from " + loc,2);
1587 
1588  if (loc.empty())
1589  error("No location supplied for the import"+ns,2);
1590 
1591  xParser_->nextTag();
1592  return true;
1593 }
1594 
1595 bool SchemaParser::isBasicType(int sType) const
1596 {
1597  if (sType > Schema::XSD_ANYURI || sType <= Schema::XSD_INVALID)
1598  return false;
1599 
1600  else
1601  return true;
1602 }
1603 
1604 
1605 //This function gets the id of a type whose Qname is passed.
1606 //The Qname struct if it has a prefix must either be a valid namespace
1607 //default is http://www.w3.org/2001/XMLSchema
1608 //This function has two modes
1609 //if 'create' is true a new type is created (for fwd references)
1610 //otherwise the existing list of parsed types is used for resolution
1611 
1612 int
1613 SchemaParser::getTypeId( const Qname & type, bool create)
1614 {
1615  std::string typens = type.getNamespace();
1616  if (typens.empty()||
1617  typens == tnsUri_ ||
1618  typens == Schema::SchemaUri){
1619 
1620  return typesTable_.getTypeId(type, create);
1621  }
1622  else {
1623  //postpone resolution till matchExtRefs is called
1624  if (importedSchemas_.size() == 0 && create) {
1625 
1626  return typesTable_.addExternalTypeId(type, 0);
1627  }
1628 
1629  //search in the array of imported schemas
1630  int typeId = 0;
1631  for (size_t i = 0; i < importedSchemas_.size(); i++) {
1632 
1633  if ( importedSchemas_[i].ns == type.getNamespace()) {
1634 
1635  if(importedSchemas_[i].sParser ) {
1636 
1637  typeId = importedSchemas_[i].sParser->getTypeId(type, false);
1638  //get the type definition from the imported namespace schema parser and
1639  // add a reference to the current schema parser
1640  if (typeId) {
1641  return typesTable_.addExternalTypeId(type,
1642  (XSDType *) importedSchemas_[i].sParser->getType(typeId));
1643  }
1644  else
1645  return 0;
1646  }
1647  }
1648  }
1649  if (create){
1650  //automatically add an unreferenced namespace as an import
1651  addImport(type.getNamespace());
1652  return typesTable_.addExternalTypeId(type, 0);
1653  }
1654  }
1655  return XSD_INVALID;
1656 }
1657 
1658 
1659 //resolves any external references with the imported schemas
1660 //This method must be called to ensure resolution of all types
1662 {
1663  int unresolved=typesTable_.getNumExtRefs();
1664  if(unresolved > 0) {
1665  for (int i = 0; i < unresolved; i++){
1666 
1667  Qname & type = typesTable_.getExtRefName(i);
1668  int localId = typesTable_.getExtRefType(i);
1669 
1670  //search in the array of imported schemas
1671  int typeId = 0;
1672  for (size_t n = 0; n < importedSchemas_.size(); n++)
1673  {
1674  if (importedSchemas_[n].ns == type.getNamespace())
1675  {
1676  if(importedSchemas_[n].sParser){
1677  typeId = importedSchemas_[n].sParser->getTypeId(type);
1678  if (typeId != 0)
1679  typesTable_.addExtType((XSDType *) importedSchemas_[n].sParser->getType(typeId),
1680  localId);
1681  }
1682  }
1683  }
1684 
1685  if (typeId == 0) {
1686 
1687  logFile_<<"Undefined type "<<type<<std::endl;
1688  }
1689  }
1690  }
1691  if (typesTable_.detectUndefinedTypes())
1692  {
1693  typesTable_.printUndefinedTypes(logFile_);logFile_.flush();
1694  logFile_<<"Unresolved types in namespace "<<tnsUri_<<std::endl;
1695  return false;
1696  }
1697 
1698  else{
1699 
1700  return true;
1701  }
1702 
1703 }
1704 
1705 
1706 //resolves any forward references of the kind<element ref=Qname... >
1707 void
1708 SchemaParser::resolveForwardElementRefs()
1709 {
1710  bool errors=false;
1711  if (lForwardElemRefs_.empty())
1712  return;
1713  for (list < Qname >::iterator pQnames = lForwardElemRefs_.begin();
1714  pQnames != lForwardElemRefs_.end(); pQnames++) {
1715 
1716  // cout<<*pQnames<<std::endl;
1717  Element *e = const_cast<Element*>(getElement(*pQnames));
1718  //TODO , in case the forward ref is in an imported schema we cant just copy the type id
1719  //it needs to be changed to make it a valid type id in current schema
1720  if (e)
1721  typesTable_.resolveForwardElementRefs(pQnames->getLocalName(),*e);
1722  else {
1723  error("Could not resolve element reference "+pQnames->getLocalName(),1);
1724  errors=true;
1725  }
1726  }
1727  if(errors)
1728  error("Unresolved element references",1);
1729 }
1730 
1731 
1732 void
1733 SchemaParser::resolveForwardAttributeRefs()
1734 {
1735  bool errors=false;
1736  if (lForwardAttributeRefs_.empty())
1737  return;
1738  for (list < Qname >::iterator pQnames = lForwardAttributeRefs_.begin();
1739  pQnames != lForwardAttributeRefs_.end(); pQnames++)
1740  {
1741  Attribute *a = getAttribute(*pQnames);
1742  if (a)
1743  typesTable_.resolveForwardAttributeRefs(pQnames-> getLocalName(), *a);
1744  else {
1745  error("Could not resolve attribute reference {"+pQnames->getNamespace()
1746  +"}"+pQnames->getLocalName(),1);
1747  errors=true;
1748  }
1749  }
1750  if(errors)
1751  error("Unresolved attributes references");
1752 }
1753 
1754 
1755 //get the element id of a globally declared element
1756 const Element*
1757 SchemaParser::getElement(const Qname & element,bool checkImports)const
1758 {
1759  std::string typens = element.getNamespace();
1760  if (typens.empty())
1761  typens = tnsUri_;
1762  if (typens== tnsUri_ || typens == Schema::SchemaUri)
1763  {
1764  int i = 0;
1765  //check if it is a global element
1766  for (std::list<Element>::const_iterator eli=lElems_.begin();
1767  eli!= lElems_.end();
1768  eli++,i++)
1769  if (eli->getName() == element.getLocalName())
1770  return &(*eli);
1771  return 0;
1772  }
1773  else if (checkImports)
1774  { //search imported namespaces
1775  for (size_t i = 0; i < importedSchemas_.size(); i++)
1776  {
1777  if ( importedSchemas_[i].ns == typens)
1778  {
1779  if(importedSchemas_[i].sParser )
1780  {
1781  return importedSchemas_[i].sParser->getElement(element);
1782  }
1783  }
1784  }
1785  }
1786  return 0;
1787 }
1788 
1789 //get the attribute id of a globally declared attribute
1790 Attribute*
1792 {
1793  std::string typens = attribute.getNamespace();
1794  if (typens.empty())
1795  typens = tnsUri_;
1796 
1797  if (typens == tnsUri_ || typens == Schema::SchemaUri) {
1798  //check if it is a global attribute
1799  for(std::list<Attribute>::iterator ali=lAttributes_.begin();
1800  ali!=lAttributes_.end();
1801  ali++)
1802  if (ali->getName() == attribute.getLocalName())
1803  return &(*ali);
1804  }else {
1805  //search imported namespaces
1806  for (size_t i = 0; i < importedSchemas_.size(); i++)
1807  {
1808  if ( importedSchemas_[i].ns == typens)
1809  {
1810  if(importedSchemas_[i].sParser )
1811  {
1812  return importedSchemas_[i].sParser->getAttribute(attribute);
1813  }
1814  }
1815  }
1816  }
1817  return 0;
1818 }
1819 
1820 //get the element id of a globally declared element
1821 Group*
1823 {
1824  std::string typens = name.getNamespace();
1825  if (typens.empty())
1826  typens = tnsUri_;
1827  if (typens== tnsUri_ || typens == Schema::SchemaUri)
1828  {
1829 
1830  //check if it is a global group
1831  for (std::list<Group>::iterator gli =lGroups_.begin();
1832  gli!= lGroups_.end();
1833  gli++)
1834  if (gli->getName() == name.getLocalName())
1835  return &(*gli);
1836  return 0;
1837  }
1838  else
1839  { //search imported namespaces
1840  for (size_t i = 0; i < importedSchemas_.size(); i++)
1841  {
1842  if ( importedSchemas_[i].ns == typens)
1843  {
1844  if(importedSchemas_[i].sParser )
1845  {
1846  return importedSchemas_[i].sParser->getGroup(name);
1847  }
1848  }
1849  }
1850  }
1851  return 0;
1852 }
1853 
1856 {
1857  std::string typens = name.getNamespace();
1858  if (typens.empty())
1859  typens = tnsUri_;
1860  if (typens== tnsUri_ || typens == Schema::SchemaUri)
1861  {
1862 
1863  //check if it is a global group
1864  for (AttributeGroupList::iterator agli = lAttributeGroups_.begin();
1865  agli!= lAttributeGroups_.end();
1866  agli++)
1867  if ((*agli)->getName() == name.getLocalName())
1868  return (*agli);
1869  return 0;
1870  }
1871  else
1872  { //search imported namespaces
1873  for (size_t i = 0; i < importedSchemas_.size(); i++)
1874  {
1875  if ( importedSchemas_[i].ns == typens)
1876  {
1877  if(importedSchemas_[i].sParser )
1878  {
1879  return importedSchemas_[i].sParser->getAttributeGroup(name);
1880  }
1881  }
1882  }
1883  }
1884  return 0;
1885 }
1886 
1887 std::string
1889 {
1890  return tnsUri_;
1891 }
1892 
1893 
1894 const XSDType *
1896 {
1897  return (const XSDType *) typesTable_.getTypePtr(id);
1898 }
1899 
1900 
1901 const XSDType *
1902 SchemaParser::getType(const Qname & type,bool checkImports )
1903 {
1904  int id;
1905  Qname t=type;
1906 
1907  if((id=getTypeId(t,false))==0)
1908  return 0;
1909  else {
1910  const XSDType* pType = (const XSDType *) typesTable_.getTypePtr(id);
1911  if (!checkImports) {
1912 
1913  if(pType->getNamespace() != tnsUri_)
1914  return 0;
1915 
1916  }
1917  return pType;
1918  }
1919 }
1920 
1921 
1922  const XSDType *
1923  SchemaParser::getType(int id, std::string &nameSpace)
1924  {
1925  const SchemaParser *sp = getImportedSchema(nameSpace);
1926  if (sp == NULL)
1927  {
1928  return 0;
1929  }
1930  else
1931  {
1932  return sp->getType(id);
1933  }
1934  }
1935 
1936  const SchemaParser *
1937  SchemaParser::getImportedSchema(std::string &nameSpace)
1938  {
1939  if (nameSpace.empty()|| nameSpace == tnsUri_ || nameSpace == Schema::SchemaUri)
1940  {
1941  return this;
1942  }
1943 
1944  for (size_t i = 0; i < importedSchemas_.size(); i++)
1945  {
1946  if ( importedSchemas_[i].ns == nameSpace)
1947  {
1948  return importedSchemas_[i].sParser;
1949  }
1950  }
1951  return NULL;
1952  }
1953 
1954 list < const XSDType *>*
1956 {
1957  list < const XSDType *>*pLTypes = new list < const XSDType * >;
1958  for (int i = 0; i < getNumTypes(); i++)
1959  {
1960  const XSDType *pType = getType(i + Schema::XSD_ANYURI + 1);
1961  pLTypes->push_back(pType);
1962  }
1963  return pLTypes;
1964 }
1965 
1966 
1967 int
1969 {
1970  return typesTable_.getNumTypes();
1971 }
1972 
1973 
1974 int
1976 {
1977  return lElems_.size();
1978 }
1979 
1980 
1981 int
1983 {
1984  return lAttributes_.size();
1985 }
1986 
1987 //To be deprecated
1988 bool
1989 SchemaParser::addImports(const std::vector<SchemaParser *> & schemaParsers)
1990 {
1991  for (size_t i=0;i<schemaParsers.size() ;i++){
1992 
1993  if(schemaParsers[i]->getNamespace()!=tnsUri_){
1994 
1995  addImport(schemaParsers[i]);
1996  }
1997  }
1998  return true;
1999 }
2000 
2001 bool
2003 {
2004  //check if the namespace is added in the import list
2005  int i= checkImport(sp->getNamespace());
2006  // std::cout<<"Copying imports to "<<sp->tnsUri_<<std::endl;
2007  // sp->copyImports(this);
2008  if(i>=0) {
2009  importedSchemas_[i].sParser=sp;
2010  importedSchemas_[i].ns=sp->getNamespace();
2011  }
2012  else {
2013  //if this was a new import increment
2014  ImportedSchema imp;
2015  imp.sParser=sp;
2016  imp.ns=sp->getNamespace();
2017  importedSchemas_.push_back(imp);
2018  }
2019  return true;
2020 }
2021 
2022 void
2023 SchemaParser::copyImports(SchemaParser * sp)
2024 {
2025  for(size_t i=0;i<importedSchemas_.size();i++) {
2026 
2027  if (importedSchemas_[i].sParser)
2028  sp->addImport(importedSchemas_[i].sParser);
2029  }
2030 }
2031 
2032 int
2033 SchemaParser::checkImport(std::string nsp)const
2034 {
2035  for(size_t i=0;i<importedSchemas_.size();i++)
2036  {
2037  if(importedSchemas_[i].ns==nsp)
2038  return i;
2039  }
2040  return -1;
2041 }
2042 
2043 bool
2045  std::string location)
2046 {
2047 
2048  int i= checkImport(ns);
2049  if(i==-1) {
2050  ImportedSchema imp;
2051  imp.sParser=0;
2052  imp.ns=ns;
2053  importedSchemas_.push_back(imp);
2054  i =importedSchemas_.size()-1;
2055  }else {
2056  return true;
2057  }
2058 
2059  if(location.empty())
2060  return true;
2061  std::string xsdFile;
2062  if(XmlUtils::fetchUri(location,xsdFile))
2063  {
2064  /*
2065  * If the schema definition was retrieved successfully
2066  * process it and add it to list of imported schemas
2067  */
2068  SchemaParser *sp = new SchemaParser(xsdFile,ns);
2069  sp->setUri(uri_);
2070  if(sp->parseSchemaTag())
2071  {
2072  importedSchemas_[i].sParser=sp;
2073  return true;
2074  }
2075  else return false;
2076  }
2077  else return false;
2078 
2079 }
2080 
2081 
2082 void SchemaParser::error(std::string mesg, int level)
2083 {
2084 
2085  if (level == 0) {
2086 
2087  SchemaParserException spe(mesg + "\nFatal Error in SchemaParser\n");
2088  spe.line = xParser_->getLineNumber();
2089  spe.col = xParser_->getColumnNumber();
2090  throw spe;
2091  }
2092 
2093  else if (level_ >=1 && level == 1){
2094 
2095  logFile_ << "Error @" << xParser_->
2096  getLineNumber() << ":" << xParser_->
2097  getColumnNumber() << XmlUtils::dbsp << mesg << endl;
2098  }
2099  else if (level_ >= 2 && level == 2) {
2100 
2101  logFile_ << "Alert @" << xParser_->
2102  getLineNumber() << ":" << xParser_->
2103  getColumnNumber() << XmlUtils::dbsp << mesg << endl;
2104 
2105  }
2106 }
2107 
2108 
2109 int
2111 {
2112  const XSDType *pType = getType(typeId);
2113  int id = typeId;
2114  if (pType != 0) {
2115 
2116  /*
2117  It could be a complex type with
2118  simple content or a schema defined simpleType
2119  */
2120  if (pType->isSimple() == false){
2121 
2122  const ComplexType * cType= static_cast<const ComplexType*> (pType);
2123 
2124  if(cType->getContentModel()==Schema::Simple){
2125 
2126  id = cType->getContentType();
2127  }
2128  else {
2129 
2130  return Schema::XSD_INVALID;
2131  }
2132  }
2133  else{
2134 
2135  id = (static_cast<const SimpleType *>(pType))->getBaseTypeId();
2136  }
2137  id = getBasicContentType(id);
2138  }
2139  return id;
2140 }
2141 
2142 std::string
2144 {
2145  if (isBasicType(t)){
2146  return typesTable_.getAtomicTypeName(t);
2147  }
2148  else {
2149  const XSDType * pType = (const XSDType *) typesTable_.getTypePtr(t);
2150  if (pType)
2151  return pType->getName();
2152  }
2153  return "";
2154 }
2155 
2156 
2157 //handle soap arrays .this is really a special case.more like a hack
2158 bool
2159 SchemaParser::makeListFromSoapArray (ComplexType * ct)
2160 {
2161  const XSDType * baseType=getType(ct->getBaseTypeId());
2162  if (baseType) {
2163  if(baseType->getNamespace()== "http://schemas.xmlsoap.org/soap/encoding/" &&
2164  baseType->getName()=="Array"){
2165 
2166  const Attribute* a = ct->getAttribute("arrayType");
2167  if (!a)
2168  return false;
2169 
2170  std::string array = a->defaultVal();
2171  Qname q(array);
2172  array = q.getLocalName();
2173  while (array[array.length()-1] ==']' &&
2174  array[array.length()-2] =='[')
2175  array = array.substr(0,array.length()-2);
2176 
2177  std::string arrayNs = xParser_->getNamespace(q.getPrefix());
2178  q = Qname(array);
2179  q.setNamespace(arrayNs);
2180  Schema::Type t = (Schema::Type)getTypeId(q,true);
2181  Element e("*",tnsUri_,tnsUri_,t,0,UNBOUNDED);
2182  if (ct->getContents() == 0){
2184  ct->setContents(cm);
2185  }
2186  ct->getContents()->addElement(e);
2187  return true;
2188  }
2189  }
2190  return false;
2191 }
2192 }