src/schemaparser/SchemaParser.cpp

00001 /* 
00002  * wsdlpull - A C++ parser  for WSDL  (Web services description language)
00003  * Copyright (C) 2005-2007 Vivek Krishna
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the Free
00016  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  *
00018  *
00019  */
00020 
00021 #include "schemaparser/SchemaParser.h"
00022 
00023 #ifndef _WIN32
00024 #include "xmlpull/ConfigFile.h"
00025 #endif
00026 
00027 namespace Schema {
00028 using namespace std;
00029 SchemaParser::SchemaParser(XmlPullParser * parser, 
00030                            std::string tns,
00031                            std::ostream & log,
00032                            const std::string & s)
00033   :tnsUri_(tns), 
00034    xParser_(parser),
00035    elementQualified_ (false),
00036    attributeQualified_ (false),
00037    deleteXmlParser_(false),
00038    resolveFwdRefs_(true),
00039    level_(1),
00040    logFile_(log),
00041    confPath_(s)
00042 {
00043   init();
00044 }
00045 
00046 SchemaParser::SchemaParser(const std::string &Uri, 
00047                            std::string tns , 
00048                            std::ostream & log ,
00049                            const std::string & s)
00050   :tnsUri_(tns),
00051    xParser_(0),
00052    elementQualified_ (false),
00053    attributeQualified_ (false),
00054    deleteXmlParser_(false),
00055    resolveFwdRefs_(true),
00056    level_(1),
00057    logFile_(log),
00058    confPath_(s)
00059 {
00060     if(XmlUtils::fetchUri(Uri,fname_))
00061     {
00062       xmlStream_.open(fname_.c_str());
00063       xParser_ = new XmlPullParser(xmlStream_);
00064       xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true);
00065       xParser_->require(XmlPullParser::START_DOCUMENT, "", "");
00066       while (!xmlStream_.fail() && xParser_->getEventType() != xParser_->END_DOCUMENT)
00067         { 
00068           xParser_->nextTag();
00069           if (xParser_->getEventType() == xParser_->START_TAG &&
00070               xParser_->getName() == "schema")
00071             {
00072               deleteXmlParser_=true;
00073               tnsUri_=tns;
00074               break; 
00075             }
00076         }
00077 
00078     }
00079   if(!deleteXmlParser_) //something wron while opening the schema file
00080     {
00081       delete xParser_;
00082       xParser_=0;
00083     }
00084       
00085   init();
00086   uri_ = Uri.substr(0,Uri.rfind('/') + 1);
00087 }
00088 
00089 void
00090 SchemaParser::init()
00091 {
00092   lElems_.clear()   ;
00093   lAttributes_.clear();
00094   lAttributeGroups_.clear();
00095   importedSchemas_.clear();
00096   constraints_.clear();
00097 
00098   if (confPath_.empty()) {
00099 #if defined SCHEMADIR
00100     confPath_ = SCHEMADIR;
00101 #else
00102     confPath_ = "src/schemas";
00103 #endif
00104   }
00105   
00106   Element e("schema",
00107             SchemaUri,
00108             SchemaUri,
00109             Schema::XSD_SCHEMA);
00110   lElems_.push_back(e);
00111 
00112 
00113 
00114 #ifdef LOGGING
00115   level_ = 2;
00116 #endif
00117 }
00118 
00119 SchemaParser::~SchemaParser()
00120 {
00121   //clear the Types table
00122   typesTable_.clean();
00123   if(deleteXmlParser_) {
00124     
00125     delete xParser_;
00126     xmlStream_.close();
00127   }
00128    
00129   for (ConstraintList::iterator ci=constraints_.begin();
00130        ci != constraints_.end();
00131        ci++)
00132     delete *ci;
00133   for (AttributeGroupList::iterator agi = lAttributeGroups_.begin();
00134        agi != lAttributeGroups_.end();
00135        agi++)
00136     delete *agi; 
00137 }
00138 
00139 
00140 /*
00141  * Parses an schema definition.
00142  * This is the main entry method for the schema parser
00143  */
00144 bool SchemaParser::parseSchemaTag()
00145 {
00146   int i = 0;
00147   if(!xParser_)
00148     return false;
00149   while (xParser_->getEventType() != xParser_->START_TAG)
00150     xParser_->next();
00151   xParser_->require(xParser_->START_TAG, Schema::SchemaUri, "schema");
00152   int attcnt = xParser_->getAttributeCount();
00153 
00154   //parse the schema tag's attributes
00155   for (i = 0; i < attcnt; i++) {
00156     std::string attName = xParser_->getAttributeName(i);
00157     if ("targetNamespace" == attName)
00158       //store the tns URI
00159       tnsUri_ = xParser_->getAttributeValue(i);
00160     if ("version" == attName)
00161       version_ = xParser_->getAttributeValue(i);
00162     if ("elementFormDefault" == attName){
00163       if (xParser_->getAttributeValue(i) == "unqualified")
00164         elementQualified_ = false;
00165 
00166       else if (xParser_->getAttributeValue(i) == "qualified")
00167         elementQualified_ = true;
00168     }
00169     if ("attributeFormDefault" == attName) {
00170       if (xParser_->getAttributeValue(i) == "unqualified")
00171         attributeQualified_ = false;
00172 
00173       else if (xParser_->getAttributeValue(i) == "qualified")
00174         attributeQualified_ = true;
00175     }
00176   }
00177 
00178   for (i = xParser_->getNamespaceCount(xParser_->getDepth()) - 1;
00179        i > xParser_->getNamespaceCount(xParser_->getDepth() - 1) - 1; i--)
00180     if (xParser_->getNamespaceUri(i) == tnsUri_)
00181       tnsPrefix_ = xParser_->getNamespacePrefix(i);
00182   typesTable_.setTargetNamespace(tnsUri_);
00183   xParser_->nextTag();
00184 
00185   return   parseSchema();
00186 }
00187 
00188 //this function handles the schema
00189 bool
00190 SchemaParser::parseSchema(std::string tag)
00191 {
00192   try
00193     {
00194       do
00195         {
00196   
00197           if (xParser_->getEventType() == xParser_->END_TAG)
00198             {
00199               if (xParser_->getName() == tag)
00200                 break;
00201               while (xParser_->getEventType() != xParser_->START_TAG)
00202                 xParser_->nextTag();
00203             }
00204 
00205           /*
00206             This is the main loop
00207             Depending on the tag encountered call the appropriate routines
00208             Schema elements visible at this level
00209             1. Global  Element declarations
00210             2. Global attribute declarations
00211             3. Complex type and Simple type declarations
00212 
00213           */
00214           std::string elemName = xParser_->getName();
00215           if (elemName == "element") {
00216             bool fwd;
00217           Element e = parseElement(fwd);
00218           lElems_.push_back(e);
00219           }
00220           else if (elemName == "complexType")
00221             {
00222               XSDType *t = parseComplexType();
00223               typesTable_.addType(t);
00224             }
00225           else if (elemName == "simpleType")
00226             {
00227               XSDType *t = parseSimpleType();
00228               typesTable_.addType(t);
00229             }
00230           else if (elemName == "attribute") {
00231             bool fwd;
00232             lAttributes_.push_back(parseAttribute(fwd));
00233           }
00234           else if (elemName == "annotation"){
00235             parseAnnotation();
00236           }
00237           else if (elemName == "import") {
00238             parseImport();
00239           }
00240           else if (elemName=="include"){
00241             parseInclude();
00242           }
00243           else if(elemName=="attributeGroup") {
00244             AttributeGroup* ag = parseAttributeGroup();
00245             if (ag)
00246               lAttributeGroups_.push_back(ag);
00247             
00248           }else if(elemName=="group") {
00249             
00250             lGroups_.push_back(parseGroup());
00251             Group & g=lGroups_.back();
00252             //make this grp the owner of the content model
00253             g.setContents(g.getContents(),false);
00254           }
00255           else if( elemName=="key")     {
00256             
00257             constraints_.push_back(parseConstraint(Schema::Key));
00258           }
00259           else if( elemName=="keyref")  {
00260             constraints_.push_back(parseConstraint(Schema::Keyref));
00261           }
00262           else if( elemName=="unique")  {
00263             constraints_.push_back(parseConstraint(Schema::Unique));
00264           }else if (elemName=="redefine"){
00265             parseRedefine();
00266           }
00267           else {
00268             error("Unknown element "+ elemName,1);
00269             break;
00270           }
00271           xParser_->nextTag();
00272         }
00273       while (true);
00274       if ((importedSchemas_.size() == 0) &&
00275           typesTable_.detectUndefinedTypes()){
00276         
00277         typesTable_.printUndefinedTypes(logFile_);logFile_.flush();
00278         error("Undefined Types in namespace "+tnsUri_);
00279         }
00280       if(shouldResolve())
00281         {
00282             
00283           resolveForwardElementRefs();
00284           resolveForwardAttributeRefs();
00285         }
00286         
00287     }
00288   catch(SchemaParserException spe)
00289     {
00290       spe.line = xParser_->getLineNumber();
00291       spe.col = xParser_->getColumnNumber();
00292 
00293        logFile_ << spe.description << " at "
00294            << spe.line << ":" << spe.col 
00295            << std::endl;
00296 
00297       return false;
00298     }
00299   return true;
00300 }
00301 
00302 
00303 void SchemaParser::parseAnnotation()
00304 {
00305 
00306   do
00307     {
00308       xParser_->nextToken();
00309       if (xParser_->getEventType() == xParser_->END_TAG
00310           && xParser_->getName() == "annotation")
00311         break;
00312     }
00313   while (true);
00314 }
00315 
00316 
00317 ComplexType *
00318 SchemaParser::parseComplexType()
00319 {
00320   ComplexType *newType = new ComplexType(tnsUri_);
00321   int attcnt = xParser_->getAttributeCount();
00322   for (int i = 0; i < attcnt; i++)
00323     {
00324       if ("name" == xParser_->getAttributeName(i))
00325         newType->setName(xParser_->getAttributeValue(i));
00326      
00327       if ("mixed" == xParser_->getAttributeName(i) &&
00328           (xParser_->getAttributeValue(i).empty() ||
00329            xParser_->getAttributeValue(i)=="true"))
00330         
00331         newType->setContentModel(Schema::Mixed);
00332     }
00333 
00334 
00335   do
00336     {
00337       //begin parsing the complex type's children
00338       xParser_->nextTag();
00339       if (xParser_->getEventType() == xParser_->END_TAG)
00340         {
00341           if (xParser_->getName() == "complexType")
00342             break;
00343 
00344           //if an end tag is seen proceed till next start tag
00345           while (xParser_->getEventType() != xParser_->START_TAG)
00346             xParser_->nextTag();
00347         }
00348       std::string elemName = xParser_->getName();
00349       
00350       
00351       if (elemName == "all"){
00352         ContentModel * cm= new ContentModel(Schema::All);
00353         newType->setContents(cm);
00354         parseContent(cm);
00355       }
00356       else if (elemName == "sequence"){
00357         ContentModel * cm= new ContentModel(Schema::Sequence);
00358         newType->setContents(cm);
00359         parseContent(cm);
00360       }
00361       else if (elemName == "choice"){
00362         ContentModel * cm= new ContentModel(Schema::Choice);
00363         newType->setContents(cm);
00364         parseContent(cm);
00365       }
00366       else if (elemName == "attribute") {
00367         bool f=false;
00368         Attribute a=parseAttribute(f);
00369         newType->addAttribute(a,f);
00370       }else if (elemName=="attributeGroup"){
00371         parseAttributeGroup(newType);
00372       }
00373       else if (elemName=="group"){
00374         //TODO
00375         ContentModel* cm= new ContentModel(Schema::Sequence);
00376         newType->setContents(cm);
00377         parseGroup(cm);
00378       }
00379       else if (elemName == "anyAttribute")
00380         addAnyAttribute(newType);
00381 
00382       else if (elemName == "complexContent")
00383         parseComplexContent(newType);
00384 
00385       else if (elemName == "simpleContent")
00386         parseSimpleContent(newType);
00387 
00388       else if (xParser_->getName() == "annotation")
00389         parseAnnotation();
00390 
00391       else
00392         error("Unexpected tag: '"+elemName+"' in "+newType->getName() );
00393     }
00394   while (true);
00395   makeListFromSoapArray(newType);
00396   return newType;
00397 }
00398 
00399 AttributeGroup*
00400 SchemaParser::parseAttributeGroup(ComplexType* cType)
00401 {
00402   std::string name,ref;
00403   ref = xParser_->getAttributeValue("", "ref");
00404   if (!ref.empty())
00405     {
00406       Qname agRef(ref);
00407       AttributeGroup *ag= getAttributeGroup(agRef);
00408       if(cType && ag){
00409         
00410         for(list<Attribute>::iterator ai= ag->begin();
00411             ai!=ag->end();
00412             ai++)
00413           cType->addAttribute(*ai);
00414       }
00415       else if (cType){
00416         cType->addAttributeGroupName(ref);
00417       }
00418       xParser_->nextTag();    
00419       return ag;
00420     }
00421   
00422   name = xParser_->getAttributeValue("", "name");
00423   AttributeGroup *ag = new AttributeGroup(name);
00424   xParser_->nextTag();
00425   while (xParser_->getName() == "annotation")
00426     {
00427       parseAnnotation();
00428       xParser_->nextTag();
00429     }
00430   std::string elemName=xParser_->getName();
00431   while (!((xParser_->getEventType() == xParser_->END_TAG) &&
00432            (elemName == "attributeGroup"))){
00433    
00434     if(elemName=="attribute"){
00435       bool fwd;
00436       ag->addAttribute(parseAttribute(fwd));
00437     }else if(elemName=="attributeGroup"){
00438       AttributeGroup* ag1=parseAttributeGroup();
00439       for(list<Attribute>::iterator ai= ag1->begin();
00440           ai!=ag1->end();
00441           ai++)
00442         ag->addAttribute(*ai);
00443     }else if(elemName=="anyAttribute"){
00444       ag->addAttribute(addAnyAttribute(cType));
00445     }
00446     xParser_->nextTag();    
00447     elemName=xParser_->getName();
00448   }
00449   
00450   if(cType){
00451     
00452     for(list<Attribute>::iterator ai= ag->begin();
00453         ai!=ag->end();
00454         ai++)
00455       cType->addAttribute(*ai);
00456     delete ag;//dont store anonymous attribute groups
00457     ag = 0;
00458   }
00459   return ag;
00460 }
00461 
00462 Group
00463 SchemaParser::parseGroup(ContentModel* c)
00464 {
00465   int minimum = 1, maximum = 1;
00466   std::string tmp, name,ref;
00467   
00468   tmp = xParser_->getAttributeValue("", "minOccurs");
00469   if (!tmp.empty())
00470     minimum = XmlUtils::parseInt(tmp);
00471   tmp = xParser_->getAttributeValue("", "maxOccurs");
00472   if (!tmp.empty()) {
00473     if ("unbounded" == tmp)
00474       maximum = UNBOUNDED;
00475     else
00476       maximum = XmlUtils::parseInt(tmp);
00477   }
00478   ref = xParser_->getAttributeValue("", "ref");
00479   if (!ref.empty()) {
00480 
00481     Qname gName(ref);
00482     xParser_->nextTag();
00483     Group* gRef=getGroup(gName);
00484     if(gRef){
00485       Group g(*gRef);
00486       if(c)
00487         c->addGroup(g,true);
00488       return g;
00489     }
00490     else{
00491       Group g(gName.getLocalName(),minimum,maximum);
00492       if(c)
00493         c->addGroup(g,true);
00494       return g;
00495     }
00496   }
00497 
00498   name = xParser_->getAttributeValue("", "name");
00499   Group g(name,minimum,maximum);
00500   xParser_->nextTag();
00501   while (xParser_->getName() == "annotation") {
00502     parseAnnotation();
00503     xParser_->nextTag();
00504   }
00505 
00506   std::string elemName = xParser_->getName();
00507   ContentModel * cm=0;
00508   if (elemName == "all"){
00509     cm = new ContentModel(Schema::All);
00510   }
00511   else if (elemName == "sequence"){
00512     cm= new ContentModel(Schema::Sequence);
00513   }
00514   else if (elemName == "choice"){
00515     cm= new ContentModel(Schema::Choice);
00516   }
00517   g.setContents(cm,true);
00518   parseContent(cm);
00519   xParser_->nextTag();
00520 
00521   if(c)
00522     c->addGroup(g,false);
00523   return g;
00524 }
00525 
00526 void
00527 SchemaParser::parseContent(ContentModel * cm)
00528 {
00529   int minimum = 1, maximum = 1;
00530   std::string tmp;
00531 
00532   tmp = xParser_->getAttributeValue("", "minOccurs");
00533   if (!tmp.empty())
00534     minimum = XmlUtils::parseInt(tmp);
00535   tmp = xParser_->getAttributeValue("", "maxOccurs");
00536   if (!tmp.empty())
00537     {
00538       if ("unbounded" == tmp)
00539         maximum = UNBOUNDED;
00540       else
00541         maximum = XmlUtils::parseInt(tmp);
00542     }
00543   cm->setMin(minimum);
00544   cm->setMax(maximum);
00545 
00546   xParser_->nextTag();
00547   while (xParser_->getName() == "annotation")
00548     {
00549       parseAnnotation();
00550       xParser_->nextTag();
00551     }
00552 
00553   while (!((xParser_->getEventType() == xParser_->END_TAG) &&
00554            (xParser_->getName() == "choice"
00555             || xParser_->getName() == "sequence"
00556             || xParser_->getName() == "all")))
00557     {
00558       if (xParser_->getName() == "element") {
00559         bool f=false;
00560         Element e =parseElement(f);
00561         cm->addElement(e);
00562       }else if(cm->getCompositor()!=Schema::All){
00563         
00564         if (xParser_->getName() == "any")
00565           addAny(cm);
00566         else if (xParser_->getName() == "choice"){
00567           ContentModel * cmc= new ContentModel(Schema::Choice);
00568           cm->addContentModel(cmc);
00569           parseContent(cmc);  
00570         }
00571         else if (xParser_->getName() == "sequence"){
00572           ContentModel * cms= new ContentModel(Schema::Sequence);
00573           cm->addContentModel(cms);
00574           parseContent(cms);  
00575         }
00576         else if (xParser_->getName() == "group"){
00577           parseGroup(cm);
00578         }
00579         else if(xParser_->getName() == "annotation") {
00580           parseAnnotation();
00581         }
00582         else
00583           error("parseContent: Unexpected tag "+xParser_->getName());
00584       }else{
00585         
00586         error("parseContent <all>:Syntax Error");
00587       }
00588       xParser_->nextTag();
00589     }
00590 }
00591 
00592 Element
00593 SchemaParser::parseElement(bool & fwdRef)
00594 {
00595   std::string name, fixedVal, defaultVal, 
00596     // the namespace of the element is the
00597     // namespace of the sp that parsed it!
00598     typeNs = tnsUri_,elemNs = tnsUri_;
00599   Constraint* c=0;
00600   int type_id = 0, minimum = 1, maximum = 1, attcnt;
00601   Qname refName;
00602   bool qualified = false,nill = false;
00603   XSDType *elemType;
00604   fwdRef=false;
00605   attcnt = xParser_->getAttributeCount();
00606   for (int i = 0; i < attcnt; i++)
00607     {
00608       std::string attName = xParser_->getAttributeName(i);
00609       if ("name" == attName)
00610         name = xParser_->getAttributeValue(i);
00611 
00612       else if ("type" == attName)
00613         {
00614           Qname typeName(xParser_->getAttributeValue(i));
00615           if (type_id > 0)
00616             error
00617               ("<element> : type and ref are mutually exclusive in element decl");
00618           typeName.setNamespace(typeNs=xParser_->getNamespace(typeName.getPrefix()));
00619           type_id = getTypeId(typeName, true);
00620           if (type_id == 0)
00621             error("<element>:Could not resolve type " +
00622                   typeName.getNamespace() + ":" +
00623                   typeName.getLocalName(),0);
00624         }
00625 
00626       else if ("form" == attName)
00627         {
00628           if ("qualified" == xParser_->getAttributeValue(i))
00629             qualified = true;
00630 
00631           else if ("unqualified" == xParser_->getAttributeValue(i))
00632             qualified = false;
00633           else
00634             error("<element>:Invalid value for form in element " +
00635                   name,1);
00636         }
00637 
00638       else if ("ref" == attName)
00639         {
00640           if (!name.empty())
00641             error
00642               ("<element>:name and ref are mutually exclusive in element decl");
00643           if (type_id > 0)
00644             error
00645               ("<element>:type and ref are mutually exclusive in element decl");
00646           refName = xParser_->getAttributeValue(i);
00647           refName.setNamespace(xParser_->getNamespace(refName.getPrefix()));
00648           Element *e=0;
00649           elemNs = refName.getNamespace();
00650 
00651           if(refName.getNamespace()==tnsUri_){
00652 
00653             e = const_cast<Element*>(getElement(refName));
00654             if (e)
00655               type_id = e->getType();
00656           }
00657           else{
00658             //The referenced element may be in an imported schemaparser
00659             int i=checkImport(refName.getNamespace());
00660             if(i>=0 && importedSchemas_[i].sParser) {
00661            
00662               e=const_cast<Element*>(importedSchemas_[i].sParser->getElement(refName));
00663               if (e){
00664                 //if the type is in an imported schema then we must add a local reference to
00665                 // its type,because the type id as got by e->getType()
00666                 // is not valid in the current schema context
00667                 const XSDType* pType = importedSchemas_[i].sParser->getType(e->getType());
00668                 type_id= typesTable_.addExternalTypeId(e->getName()+"_"+e->getTypeNamespace(),
00669                                                        pType);
00670               }
00671             }
00672           }
00673           
00674           if (e == 0){
00675 
00676             fwdRef=true;
00677             name=refName.getLocalName();
00678             lForwardElemRefs_.push_back(refName);
00679             //this will be resolved later
00680           }
00681           else{
00682             name = e->getName();
00683             qualified = e->isQualified();
00684             defaultVal = e->defaultVal();
00685             fixedVal = e->fixedVal();
00686             typeNs = e->getTypeNamespace();
00687             elemNs = e->getNamespace();
00688           }
00689 
00690 #ifdef LOGGING
00691             logFile_<<elemNs<<":"<<name<<" ->  element reference("<<type_id<<")"<<std::endl;
00692 #endif
00693           
00694         }
00695       else if ("minOccurs" == attName){
00696         minimum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
00697       }
00698       else if ("maxOccurs" == attName){
00699         if ("unbounded" == xParser_->getAttributeValue(i))
00700           maximum = UNBOUNDED;
00701         else
00702           maximum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
00703         if (maximum == -1){                        //invalid value for maxOccurs
00704           error("<element>:Invalid value for maxOccurs",1);
00705           maximum=1;
00706         }
00707       }
00708       else if ("default" == attName){
00709         if (fixedVal.empty())
00710           defaultVal = xParser_->getAttributeValue(i);
00711 
00712         else
00713           error("<element>:fixed and default cannot occur together");
00714       }
00715       else if ("fixed" == attName){
00716         if (defaultVal.empty())
00717           fixedVal = xParser_->getAttributeValue(i);
00718 
00719         else
00720           error("<element>:fixed and default cannot occur together");
00721       }
00722 
00723       else if ("substitutionGroup" == attName) {
00724 
00725         //do nothing
00726       }
00727       else if ("nillable" == attName)  {
00728 
00729         //a nillable element need not have a type ,so set it to anyType id if nop type was given
00730         nill = true;
00731       }
00732       else
00733         error("<element>:Unsupported Attribute "+attName ,2) ;
00734     }
00735 
00736   do
00737     {
00738       xParser_->nextTag();
00739       std::string elemName=xParser_->getName();
00740       if (xParser_->getEventType() == xParser_->END_TAG) {
00741         if (elemName == "element")
00742           break;
00743 
00744         //if an end tag is seen proceed till next start tag
00745         while (xParser_->getEventType() != xParser_->START_TAG)
00746           xParser_->nextTag();
00747       }
00748 
00749       if (elemName == "complexType"){
00750         elemType = parseComplexType();
00751         type_id = typesTable_.addType(elemType);
00752         typeNs = elemType->getNamespace();
00753       }
00754       else if (elemName == "simpleType"){
00755         elemType = parseSimpleType();
00756         type_id = typesTable_.addType(elemType);
00757         typeNs = elemType->getNamespace();
00758       }
00759       else if (elemName == "annotation"){
00760         parseAnnotation();
00761       }
00762       else if( elemName=="key") {
00763         if (c)
00764           delete c;
00765         c=parseConstraint(Schema::Key);
00766       }
00767       else if( elemName=="keyref")      {
00768         if (c)
00769           delete c;
00770         c=parseConstraint(Schema::Keyref);
00771       }
00772       else if( elemName=="unique")      {
00773         if (c)
00774           delete c;
00775         c=parseConstraint(Schema::Unique);
00776       }
00777       else{
00778         error("<element> : syntax error or unkown tag :"+elemName);
00779       }
00780     }
00781   while (true);
00782   
00783   if (nill && type_id == 0) {
00784     type_id = Schema::XSD_ANYTYPE;
00785   }
00786   
00787   constraints_.push_back(c);  
00788   Element e(name,
00789             elemNs,
00790             typeNs,
00791             type_id,
00792             minimum,
00793             maximum,
00794             qualified,
00795             defaultVal,
00796             fixedVal);
00797   e.addConstraint(c);
00798   return e;
00799 }
00800 
00801 Constraint*
00802 SchemaParser::parseConstraint(Schema::ConstraintType cstr)
00803 {
00804   Constraint * c= new Constraint(cstr);
00805   c->setName(xParser_->getAttributeValue("","name"));
00806 
00807   do
00808     {
00809       xParser_->nextTag();
00810       std::string elemName=xParser_->getName();
00811       if (xParser_->getEventType() == xParser_->END_TAG) {
00812         if (cstr==Schema::Key && elemName == "key" ||
00813             cstr==Schema::Keyref && elemName == "keyref" ||
00814             cstr==Schema::Unique && elemName == "unique" )
00815           break;
00816 
00817         //if an end tag is seen proceed till next start tag
00818         while (xParser_->getEventType() != xParser_->START_TAG)
00819           xParser_->nextTag();
00820       }
00821       if(elemName=="selector"){
00822         c->setSelector(xParser_->getAttributeValue("", "xpath"));
00823         xParser_->nextTag();
00824       }
00825       else if(elemName=="field"){
00826         c->addField(xParser_->getAttributeValue("", "xpath"));
00827         xParser_->nextTag();
00828       }
00829     }while (true);
00830   return c;
00831 }
00832 
00833 
00834 Element
00835 SchemaParser::addAny(ContentModel* cm)
00836 {
00837   std::string ns;
00838   
00839   int type_id = Schema::XSD_ANY, minimum = 1, maximum = 1, attcnt;
00840   //note  processContents=lax .
00841   attcnt = xParser_->getAttributeCount();
00842   for (int i = 0; i < attcnt; i++)
00843     {
00844       std::string attr = xParser_->getAttributeName(i);
00845       if ("namespace" == attr)
00846         ns = xParser_->getAttributeValue(i);
00847 
00848       else if ("minOccurs" == attr)
00849         minimum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
00850 
00851       else if ("maxOccurs" == attr)
00852         {
00853           if ("unbounded" == xParser_->getAttributeValue(i))
00854             maximum = UNBOUNDED;
00855           else
00856             maximum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
00857           if (maximum == -1){                        //invalid value for maxOccurs
00858             error("<element>:Invalid value for maxOccurs",1);
00859             maximum=1;
00860           }
00861         }
00862 
00863       else if ("processContents" == attr || "id" == attr) {
00864         
00865         //do nothing
00866         }
00867       else
00868         error("<any>:Unsupported Attribute "+attr,2);
00869     }
00870 
00871   xParser_->nextTag();
00872   do
00873     {
00874       if (xParser_->getEventType() == xParser_->END_TAG)
00875         {
00876           if (xParser_->getName() == "any")
00877             break;
00878           
00879         }
00880       xParser_->nextToken();
00881     }while (true);
00882 
00883 
00884   Element e(ns,
00885             ns,
00886             ns,
00887             type_id,
00888             minimum,
00889             maximum);
00890   
00891   cm->addElement(e);
00892   return e;
00893 }
00894 
00895 
00896 Attribute
00897 SchemaParser::addAnyAttribute(ComplexType * cType)
00898 {
00899   std::string ns;
00900   int type_id = Schema::XSD_ANY,attcnt;
00901   bool qualified = true;
00902 
00903   //note  processContents=lax .
00904   attcnt = xParser_->getAttributeCount();
00905   for (int i = 0; i < attcnt; i++)
00906     {
00907       std::string attr = xParser_->getAttributeName(i);
00908       if ("namespace" == attr)
00909         ns = xParser_->getAttributeValue(i);
00910 
00911       else if ("processContents" == attr || "id" == attr)
00912         {
00913 
00914           //do nothing
00915         }
00916       else
00917         error("<anyAttribute>:Unsupported Attribute "+attr,1);
00918     }
00919   
00920   Attribute a(ns,
00921               type_id,
00922               qualified);
00923  if(cType)
00924    cType->addAttribute(a);
00925   xParser_->nextTag();
00926   while (xParser_->getName() == "annotation")
00927     {
00928       parseAnnotation();
00929       xParser_->nextTag();
00930     }
00931   return a;
00932   
00933 }
00934 
00935 
00936 //This function parses and attribute
00937 Attribute
00938 SchemaParser::parseAttribute(bool & fwdRef)
00939 {
00940   std::string name, fixedVal, defaultVal;
00941   int type_id = 0, attcnt;
00942   bool qualified = false, use = false;
00943   fwdRef=false;
00944   
00945   Qname refAttribute;
00946   attcnt = xParser_->getAttributeCount();
00947   for (int i = 0; i < attcnt; i++) {
00948     std::string attName = xParser_->getAttributeName(i);
00949     std::string attNs=xParser_->getAttributeNamespace(i);
00950     std::string attVal=xParser_->getAttributeValue(i);
00951     
00952     
00953     if ("name" == attName)
00954       name = attVal;
00955     else if ("type" == attName) {
00956       if (type_id > 0)
00957         error("<attribute>:type and ref are mutually exclusive in element decl");
00958       Qname typeName(attVal);
00959       typeName.setNamespace(xParser_->
00960                             getNamespace(typeName.getPrefix()));
00961       type_id = getTypeId(typeName, true);
00962       if (type_id == 0)
00963         error("<attribute>:Could not resolve type " +
00964               typeName.getNamespace() + 
00965               ":" +typeName.getLocalName(),1);
00966     }
00967     else if ("form" == attName) {
00968       if ("qualified" == attVal)
00969         qualified = true;
00970       else 
00971         qualified = false;
00972     }
00973     else if ("ref" == attName) {
00974       if (!name.empty())
00975         error("<attribute>:name and ref are mutually exclusive in element decl");
00976       if (type_id > 0)
00977         error("<attribute>:type and ref are mutually exclusive in element decl");
00978       refAttribute = attVal;
00979       refAttribute.setNamespace(xParser_->getNamespace(refAttribute.getPrefix()));
00980       Attribute *a =0;
00981       if(refAttribute.getNamespace()==tnsUri_){
00982         a=getAttribute(refAttribute);
00983       }else{
00984         int i=checkImport(refAttribute.getNamespace());
00985         if(i >=0 && importedSchemas_[i].sParser){
00986           a=importedSchemas_[i].sParser->getAttribute(refAttribute);
00987         }
00988         else
00989           a=0;
00990       }
00991           
00992       if (a == 0){
00993         fwdRef = true;
00994         name=refAttribute.getLocalName();
00995         lForwardAttributeRefs_.push_back(refAttribute);
00996       }
00997       else{
00998         name = a->getName();
00999         type_id = a->getType();
01000         qualified = a->isQualified();
01001         if (defaultVal.empty())
01002           defaultVal = a->defaultVal();
01003         if (fixedVal.empty())
01004           fixedVal = a->fixedVal();
01005       }
01006     }
01007     else if ("default" == attName) {
01008       if (fixedVal.empty())
01009         defaultVal = attVal;
01010       else
01011         error
01012           ("<attribute>:fixed and default cannot occur together");
01013     }
01014     else if ("fixed" == attName) {
01015       if (defaultVal.empty())
01016         fixedVal = attVal;
01017       else
01018         error("<attribute>:fixed and default cannot occur together");
01019     }
01020     else if ("use" == attName) {
01021       if (attVal == "required")
01022         use = true;
01023       else 
01024         use = false;
01025     }
01026     else {
01027       int n=-1;
01028       if(!attNs.empty() && ((n=checkImport(attNs))!=-1)){
01029         fixedVal=attNs;//hack for non schema attributes
01030         defaultVal=attVal;//store non schema attributes.esp for soapenc:arrayType
01031       }else{
01032         error("<attribute>:Unsupported attribute {"+ attNs+ "}:"+attName,2);
01033       }
01034     }
01035   }
01036   //Now parse the children of the attribute tag viz simpleType
01037   do
01038     {
01039       xParser_->nextTag();
01040       if (xParser_->getEventType() == xParser_->END_TAG)
01041         {
01042           if (xParser_->getName() == "attribute")
01043             break;
01044 
01045           //if an end tag is seen proceed till next start tag
01046           while (xParser_->getEventType() != xParser_->START_TAG)
01047             xParser_->nextTag();
01048         }
01049 
01050       else if (xParser_->getName() == "simpleType")
01051         {
01052           XSDType *elemType = parseSimpleType();
01053 
01054           //create an anonymous type
01055           type_id = typesTable_.addType(elemType);
01056         }
01057 
01058       else if (xParser_->getName() == "annotation")
01059         parseAnnotation();
01060       else
01061         error("<attribute>:Syntax error or unkown tag  "+xParser_->getName());
01062     }
01063   while (true);
01064 
01065   Attribute a(name,
01066               type_id,
01067               qualified,
01068               defaultVal,
01069               fixedVal,
01070               use);
01071   return a;
01072   
01073 }
01074 
01075 SimpleType *
01076 SchemaParser::parseSimpleType()
01077 {
01078   SimpleType *st = new SimpleType(tnsUri_);
01079   int basetype_id = 0;
01080   int attcnt;
01081   attcnt = xParser_->getAttributeCount();
01082   for (int i = 0; i < attcnt; i++)
01083     {
01084       if ("name" == xParser_->getAttributeName(i))
01085         st->setName(xParser_->getAttributeValue(i));
01086 
01087       else
01088         error("<simpleType> :" + xParser_->getAttributeName(i) +
01089               ":Unknown/Unsupported  attribute ",2);
01090     }
01091 
01092   do
01093     {
01094       xParser_->nextTag();
01095       if (xParser_->getEventType() == xParser_->END_TAG)
01096         {
01097           if (xParser_->getName() == "simpleType")
01098             break;
01099 
01100           //if an end tag is seen proceed till next start tag
01101           while (xParser_->getEventType() != xParser_->START_TAG)
01102             xParser_->nextTag();
01103         }
01104       if (xParser_->getName() == "restriction")
01105         {
01106           attcnt = xParser_->getAttributeCount();
01107           for (int i = 0; i < attcnt; i++)
01108             {
01109               if ("base" == xParser_->getAttributeName(i))
01110                 {
01111                   Qname typeName(xParser_->getAttributeValue(i));
01112                   typeName.setNamespace(xParser_->
01113                                         getNamespace(typeName.
01114                                                      getPrefix()));
01115                   st->setBaseType(basetype_id =
01116                                   getTypeId(typeName, true));
01117                   if (basetype_id == 0)
01118                     error("<simpleType>:" +
01119                           xParser_->getAttributeValue(i) +
01120                           ":Unknown base type ",1);
01121                 }
01122               else
01123                 error("<simpleType>:" + xParser_->getAttributeName(i) +
01124                       ":Unknown/Unsupported  attribute for <restriction>",2);
01125             }
01126           parseRestriction(st);
01127         }
01128       else if (xParser_->getName() == "union"){
01129         
01130         std::string members = xParser_->getAttributeValue("", "membersTypes");
01131         size_t s = 0;
01132         while(s < members.length()){
01133           while(members[s]==' ')s++;
01134           std::string type = members.substr(s,members.find(' ',s)-s);
01135           basetype_id = getTypeId(Qname(type));
01136           st->setUnionType(basetype_id);
01137           s+=type.length()+1;
01138         }
01139         
01140         xParser_->nextTag();
01141       } 
01142       else if(xParser_->getName() == "list"){
01143         
01144         basetype_id = getTypeId(xParser_->getAttributeValue("", "itemType"));
01145         st->setListType(basetype_id);
01146         xParser_->nextTag();
01147       }
01148       else if (xParser_->getName() == "annotation")
01149         parseAnnotation();
01150       else
01151         error("<simpleType>:Syntax error");
01152     }
01153   while (true);
01154   return st;
01155 }
01156 
01157 void 
01158 SchemaParser::parseRestriction(SimpleType * st,
01159                                ComplexType * ct)
01160 {
01161   if (st->getBaseTypeId() == 0)
01162     error("<restriction>:unkown BaseType",1);
01163 
01164   do {
01165     xParser_->nextTag();
01166     if (xParser_->getEventType() == xParser_->END_TAG)
01167       {
01168         if (xParser_->getName() == "restriction")
01169           break;
01170         else
01171           xParser_->nextTag();
01172         if (xParser_->getName() == "restriction"
01173             && xParser_->getEventType() == xParser_->END_TAG)
01174           break;
01175       }
01176     while (xParser_->getName() == "annotation") {
01177       parseAnnotation();
01178       xParser_->nextTag();
01179     }
01180     if(xParser_->getName()=="attribute" && ct!=0){
01181       bool f=false;
01182       Attribute a=parseAttribute(f);
01183       ct->addAttribute(a,f);
01184     }
01185     else if (st->isvalidFacet(xParser_->getName())){
01186       //This function also sets the facet if valid
01187 
01188       st->setFacetValue(xParser_->getName(),
01189                         xParser_->getAttributeValue("", "value"));
01190     }else{
01191       error("<restriction>:" + xParser_->getName() +
01192             " is not a valid facet /attribute for the type",1);
01193     }
01194   } while (true);
01195 }
01196 
01197 void
01198 SchemaParser::parseComplexContent(ComplexType * ct)
01199 {
01200   int attcnt = xParser_->getAttributeCount();
01201   int i = 0;
01202   Qname typeName;
01203 
01204   ct->setContentModel(Schema::Complex);
01205   xParser_->nextTag();
01206 
01207   while (xParser_->getName() == "annotation") {
01208     parseAnnotation();
01209     xParser_->nextTag();
01210   }
01211 
01212   if (xParser_->getName() == "restriction")  {
01213     attcnt = xParser_->getAttributeCount();
01214     for (i = 0; i < attcnt; i++) {
01215       if ("base" == xParser_->getAttributeName(i))
01216         {
01217           typeName = xParser_->getAttributeValue(i);
01218           typeName.setNamespace(xParser_->
01219                                 getNamespace(typeName.getPrefix()));
01220         }
01221     }
01222     ct->setBaseType(getTypeId(typeName, true),
01223                     Schema::Restriction);
01224   }
01225   else if (xParser_->getName() == "extension") {
01226     attcnt = xParser_->getAttributeCount();
01227     for (i = 0; i < attcnt; i++) {
01228       if ("base" == xParser_->getAttributeName(i))  {
01229         typeName = xParser_->getAttributeValue(i);
01230         typeName.setNamespace(xParser_->
01231                               getNamespace(typeName.getPrefix()));
01232       }
01233     }
01234     ct->setBaseType(getTypeId(typeName, true),
01235                     Schema::Extension);
01236   }
01237   
01238   xParser_->nextTag();
01239   while (xParser_->getName() == "annotation") {
01240     parseAnnotation();
01241     xParser_->nextTag();
01242   }
01243   
01244   {
01245     std::string elemName=xParser_->getName();
01246     ContentModel * cm=0;      
01247     if (elemName == "all"){
01248       cm= new ContentModel(Schema::All);
01249     }
01250     else if (elemName == "sequence"){
01251       cm= new ContentModel(Schema::Sequence);
01252     }
01253     else if (elemName == "choice"){
01254       cm= new ContentModel(Schema::Choice);
01255     }
01256 
01257     if(cm){
01258       parseContent(cm);
01259       ct->setContents(cm);
01260       xParser_->nextTag();
01261     }
01262 
01263     //parse any attributes
01264     while (xParser_->getEventType() != xParser_->END_TAG){
01265       
01266       if (xParser_->getName() == "attribute") {
01267         bool f=false;
01268         Attribute a=parseAttribute(f);
01269         ct->addAttribute(a,f);
01270       }
01271       else if(xParser_->getName() == "attributeGroup")
01272         {
01273           parseAttributeGroup(ct);
01274           
01275         }
01276       else if (xParser_->getName() == "anyAttribute")
01277         addAnyAttribute(ct);
01278       
01279       xParser_->nextTag();
01280     }
01281   }
01282   
01283   do {
01284     if (xParser_->getEventType() == xParser_->END_TAG)
01285       if ((xParser_->getName() == "restriction" ||
01286            xParser_->getName() == "extension") ) 
01287         break;
01288     xParser_->nextTag();
01289   }
01290   while (true);
01291   
01292   xParser_->nextTag();
01293 }
01294 
01295 
01296 void
01297 SchemaParser::parseSimpleContent(ComplexType * ct)
01298 {
01299   ct->setContentModel(Schema::Simple);
01300   xParser_->nextTag();
01301   if (xParser_->getName() == "restriction")
01302     {
01303       SimpleType *st = new SimpleType(tnsUri_);
01304       int attcnt = xParser_->getAttributeCount();
01305       int basetype_id = 0;
01306       for (int i = 0; i < attcnt; i++)
01307         {
01308           if ("base" == xParser_->getAttributeName(i))
01309             {
01310               Qname typeName(xParser_->getAttributeValue(i));
01311               typeName.setNamespace(xParser_->
01312                                     getNamespace(typeName.getPrefix()));
01313               st->setBaseType(basetype_id = getTypeId(typeName, true));
01314               if (basetype_id == 0)
01315                 error("<simpleContent> :" +
01316                       xParser_->getAttributeValue(i) +
01317                       ":Unknown base type ",1);
01318             }
01319 
01320           else
01321             error("<simpleContent> :" + xParser_->getAttributeName(i) +
01322                   ":Unknown/Unsupported  attribute ",2);
01323         }
01324       parseRestriction(st,ct);
01325       int typeId = typesTable_.addType(st);
01326       ct->setSimpleContentType(typeId);
01327     }
01328 
01329   else if (xParser_->getName() == "extension")
01330     {
01331       //This extension does not use the full model that can come in
01332       //ComplexContent .It uses the simple model.no particle allowed ,only attributes
01333       int attcnt = xParser_->getAttributeCount();
01334       int basetype_id = 0;
01335       for (int i = 0; i < attcnt; i++)
01336         {
01337           if ("base" == xParser_->getAttributeName(i))
01338             {
01339               Qname typeName(xParser_->getAttributeValue(i));
01340               typeName.setNamespace(xParser_->
01341                                     getNamespace(typeName.getPrefix()));
01342               ct->setSimpleContentType(basetype_id =
01343                                        getTypeId(typeName, true));
01344               if (basetype_id == 0)
01345                 error("<simpleContent> :" +
01346                       xParser_->getAttributeValue(i) +
01347                       ":Unknown base type ",1);
01348             }
01349 
01350           else
01351             error("<simpleContent> :" + xParser_->getAttributeName(i) +
01352                   ":Unknown/Unsupported  attribute ");
01353         }
01354       xParser_->nextTag();
01355       do
01356         {
01357           
01358           if (xParser_->getName() == "attribute")
01359             {
01360               bool f=false;
01361               Attribute a=parseAttribute(f);
01362               ct->addAttribute(a,f);
01363 
01364 
01365             }
01366           else if(xParser_->getName() == "attributeGroup")
01367             {
01368               parseAttributeGroup(ct);
01369 
01370             }
01371           else
01372             break;
01373           xParser_->nextTag();
01374         }while(true);
01375       
01376       if (!
01377           (xParser_->getName() == "extension"
01378            && xParser_->getEventType() == xParser_->END_TAG))
01379         error("<simpleContent> :Syntax error :extension");
01380     }
01381   xParser_->nextTag();
01382   if (!
01383       (xParser_->getName() == "simpleContent"
01384        && xParser_->getEventType() == xParser_->END_TAG))
01385     error("<simpleContent> :Syntax error ");
01386 }
01387 
01388 
01389 bool
01390 SchemaParser::parseRedefine()
01391 {
01392   parseInclude();
01393   resolveFwdRefs_=false;
01394   parseSchema("redefine");
01395   resolveFwdRefs_=true;
01396   return true;
01397 }
01398 
01399 bool
01400 SchemaParser::parseInclude()
01401 {
01402   ifstream xsdStream;
01403   std::string loc = xParser_->getAttributeValue("", "schemaLocation");
01404 
01405 
01406   // FV Sat Dec 22 15:33:09 CET 2007 I added the absolute path and the file:/ use-cases 
01407   //in the the test. Will not work for paths like "C:\temp\schema.xsd" .Use the file:/ protocol
01408 
01409 
01410   if ( loc.find("/",0)      != 0                 &&         // not an asolute path
01411        loc.find("file:/",0) == std::string::npos &&
01412        loc.find("http://")  == std::string::npos)
01413     loc = uri_ + loc;
01414 
01415 
01416 #ifndef _WIN32
01417   
01418   if (!loc.empty()) {
01419     
01420     std::string schemaconf= confPath_ + "schema.conf";
01421     try {
01422     ConfigFile cf(schemaconf);
01423     cf.readInto<std::string>(loc,loc);
01424     }catch (const ConfigFile::file_not_found & e) {}
01425   }
01426 #endif
01427   
01428   
01429   if(!loc.empty())
01430     {
01431       if(XmlUtils::fetchUri(loc,fname_))
01432         {
01433           /*
01434            * If the schema definition was retrieved successfully 
01435            * process it and add all type definitions and
01436            * declaration to the current namespace
01437            */
01438         xsdStream.open(fname_.c_str());
01439             
01440           XmlPullParser * xpp = new XmlPullParser(xsdStream);
01441           XmlPullParser * tmpXparser=xParser_;
01442           xParser_=xpp;
01443 
01444           xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true);
01445           xParser_->require(XmlPullParser::START_DOCUMENT, "", "");
01446           while (xParser_->getEventType() != xParser_->END_DOCUMENT){ 
01447             xParser_->nextTag();
01448             if (xParser_->getEventType() == xParser_->START_TAG &&
01449                 xParser_->getName() == "schema"){
01450               resolveFwdRefs_=false;
01451                    
01452               if(!parseSchemaTag())
01453                 error("Error while parsing the included schema " + loc);
01454               else{
01455 
01456                 resolveFwdRefs_=true;  
01457                 break;
01458               }
01459             }
01460           }
01461           xParser_=tmpXparser;
01462           delete xpp;
01463         }
01464       else{
01465           
01466           error("Error while opening the included schema " + loc);
01467         }
01468     }
01469   else{
01470 
01471       error("schemaLocation is a required attribute for <include>");
01472     }
01473           
01474   xParser_->nextTag();
01475   return true;
01476 }
01477 
01478 bool
01479 SchemaParser::parseImport()
01480 {
01481   Qname typeName;
01482   std::string xsdFile;
01483   std::string ns = xParser_->getAttributeValue("", "namespace");
01484   std::string loc=xParser_->getAttributeValue("", "schemaLocation");
01485 
01486   if(ns == tnsUri_)
01487     return parseInclude();//sometimes import is used to import schemas in same ns.
01488                           //treat it internally like include
01489 
01490   //  if (loc.empty()) 
01491   //    loc = ns; //try using the namespace as schemalocation
01492   
01493   // FV Sat Dec 22 15:33:09 CET 2007 I added the absolute path and the file:/ use-cases in the the test
01494 //   if ( !loc.empty() && loc.find("http://") == std::string::npos)
01495 //      loc = uri_ + loc;
01496 
01497   if ( !loc.empty() &&
01498        loc.find("/",0)      != 0                 &&         // no an asolute path
01499        loc.find("file:/",0) == std::string::npos &&
01500        loc.find("http://")  == std::string::npos)
01501     loc = uri_ + loc;
01502   
01503 #ifndef _WIN32 
01504   if (!loc.empty()) {
01505     
01506     std::string schemaconf= confPath_ + "schema.conf";
01507     try {
01508       ConfigFile cf(schemaconf);
01509       cf.readInto<std::string>(loc,loc);
01510     }catch (const ConfigFile::file_not_found &e) {}
01511   }
01512 #endif
01513   
01514   if(!loc.empty())
01515     {
01516       if(XmlUtils::fetchUri(loc,xsdFile))
01517         {
01518           /*
01519            * If the schema definition was retrieved successfully 
01520            * process it and add it to list of imported schemas
01521            */
01522           SchemaParser *sp = new SchemaParser(xsdFile,ns);
01523           sp->setUri(uri_);
01524           //pass the imports to the new schema parser
01525           for (size_t i = 0; i < importedSchemas_.size(); i++) {
01526         
01527             if(importedSchemas_[i].sParser ) {
01528               sp->addImport(importedSchemas_[i].sParser);
01529             }
01530           }
01531 
01532           if(sp->parseSchemaTag())
01533             addImport(sp);
01534           else
01535             error("Error while parsing imported namespace "+ns,0);
01536                
01537         }
01538       else{
01539         
01540         error("could not import namespace from location "+loc);
01541       }
01542     }
01543   else{
01544     // if no location is mentioned ,just add the namespace,types will be resolved later
01545     
01546     addImport(ns);
01547   }
01548 
01549   error("Imported namespace "+ns+"  from " + loc,2);
01550 
01551   if (loc.empty()) 
01552     error("No location supplied for the import"+ns,2);
01553 
01554   xParser_->nextTag();
01555   return true;
01556 }
01557 
01558 bool SchemaParser::isBasicType(int sType) const
01559 {
01560   if (sType > Schema::XSD_ANYURI || sType <= Schema::XSD_INVALID)
01561     return false;
01562 
01563   else
01564     return true;
01565 }
01566 
01567 
01568 //This function gets the id of a type whose Qname is passed.
01569 //The Qname struct if it has a prefix must either be a valid namespace
01570 //default is http://www.w3.org/2001/XMLSchema
01571 //This function has two modes
01572 //if 'create' is true a new type is created (for fwd references)
01573 //otherwise the existing list of parsed types is used for resolution
01574 
01575 int
01576 SchemaParser::getTypeId( const Qname &  type, bool create)
01577 {
01578   std::string typens = type.getNamespace();
01579   if (typens.empty()||
01580       typens == tnsUri_ ||
01581       typens == Schema::SchemaUri){
01582 
01583     return typesTable_.getTypeId(type, create);
01584   }
01585   else {
01586     //postpone resolution till matchExtRefs is called
01587     if (importedSchemas_.size() == 0  && create) {                
01588       
01589       return typesTable_.addExternalTypeId(type, 0);
01590     }
01591 
01592     //search in the array of imported schemas
01593     int typeId = 0;
01594     for (size_t i = 0; i < importedSchemas_.size(); i++) {
01595         
01596       if ( importedSchemas_[i].ns == type.getNamespace()) {
01597 
01598         if(importedSchemas_[i].sParser ) {
01599 
01600           typeId = importedSchemas_[i].sParser->getTypeId(type, false);
01601           //get the type definition from the imported namespace schema parser and 
01602           // add a reference to the current schema parser
01603           if (typeId) {
01604             return typesTable_.addExternalTypeId(type,
01605                                                  (XSDType *) importedSchemas_[i].sParser->getType(typeId));
01606           }
01607           else
01608             return 0;
01609         }
01610       }
01611     }
01612     if (create){
01613           //automatically add an unreferenced namespace as an import
01614       addImport(type.getNamespace()); 
01615       return typesTable_.addExternalTypeId(type, 0);
01616         }
01617   }
01618   return XSD_INVALID;
01619 }
01620 
01621 
01622 //resolves any external references with  the imported schemas
01623 //This method must be called to ensure resolution of all types
01624 bool SchemaParser::finalize(void)
01625 {
01626   int unresolved=typesTable_.getNumExtRefs();
01627   if(unresolved > 0) {
01628     for (int i = 0; i < unresolved; i++){
01629     
01630       Qname & type = typesTable_.getExtRefName(i);
01631       int localId = typesTable_.getExtRefType(i);
01632 
01633       //search in the array of imported schemas
01634       int typeId = 0;
01635       for (size_t n = 0; n < importedSchemas_.size(); n++)
01636         {
01637           if (importedSchemas_[n].ns == type.getNamespace())
01638             {
01639               if(importedSchemas_[n].sParser){
01640                 typeId = importedSchemas_[n].sParser->getTypeId(type);
01641                 if (typeId != 0)
01642                   typesTable_.addExtType((XSDType *) importedSchemas_[n].sParser->getType(typeId),
01643                                          localId);
01644               }
01645             }
01646         }
01647       
01648       if (typeId == 0) {
01649         
01650         logFile_<<"Undefined type "<<type<<std::endl;
01651       }
01652     }
01653   }
01654   if (typesTable_.detectUndefinedTypes())
01655     {
01656       typesTable_.printUndefinedTypes(logFile_);logFile_.flush();
01657       logFile_<<"Unresolved types in namespace "<<tnsUri_<<std::endl;
01658       return false;
01659     }
01660 
01661   else{
01662     
01663     return true;
01664   }
01665   
01666 }
01667 
01668 
01669 //resolves any forward references of the kind<element ref=Qname... >
01670 void
01671 SchemaParser::resolveForwardElementRefs()
01672 {
01673   bool errors=false;
01674   if (lForwardElemRefs_.empty())
01675     return;
01676   for (list < Qname >::iterator pQnames = lForwardElemRefs_.begin();
01677        pQnames != lForwardElemRefs_.end(); pQnames++) {
01678     
01679     // cout<<*pQnames<<std::endl;
01680     Element *e = const_cast<Element*>(getElement(*pQnames));
01681     //TODO , in case the forward ref is in an imported schema we cant just copy the type id
01682     //it needs to be changed to make it a valid type id in current schema
01683     if (e)
01684       typesTable_.resolveForwardElementRefs(pQnames->getLocalName(),*e);
01685     else {
01686       error("Could not resolve element reference "+pQnames->getLocalName(),1);
01687       errors=true;
01688     }
01689   }
01690   if(errors)
01691     error("Unresolved element references",1);
01692 }
01693 
01694 
01695 void
01696 SchemaParser::resolveForwardAttributeRefs()
01697 {
01698   bool errors=false;
01699   if (lForwardAttributeRefs_.empty())
01700     return;
01701   for (list < Qname >::iterator pQnames = lForwardAttributeRefs_.begin();
01702        pQnames != lForwardAttributeRefs_.end(); pQnames++)
01703     {
01704       Attribute *a = getAttribute(*pQnames);
01705       if (a)
01706         typesTable_.resolveForwardAttributeRefs(pQnames-> getLocalName(), *a);
01707       else {
01708         error("Could not resolve attribute reference  {"+pQnames->getNamespace()
01709                +"}"+pQnames->getLocalName(),1);
01710         errors=true;
01711       }
01712     }
01713   if(errors)
01714     error("Unresolved attributes references");
01715 }
01716 
01717 
01718 //get the element id of a globally declared element
01719 const Element*
01720 SchemaParser::getElement(const Qname & element)const
01721 {
01722   std::string typens = element.getNamespace();
01723   if (typens.empty())
01724     typens = tnsUri_;
01725   if (typens== tnsUri_ || typens == Schema::SchemaUri)
01726     {
01727       int i = 0;
01728       //check if it is a global element
01729       for (std::list<Element>::const_iterator eli=lElems_.begin();
01730            eli!= lElems_.end();
01731            eli++,i++)
01732         if (eli->getName() == element.getLocalName())
01733           return &(*eli);
01734       return 0;
01735     }
01736   else
01737     { //search imported namespaces
01738       for (size_t i = 0; i < importedSchemas_.size(); i++)
01739         {
01740           if ( importedSchemas_[i].ns == typens)
01741             {
01742               if(importedSchemas_[i].sParser )
01743                 {
01744                   return importedSchemas_[i].sParser->getElement(element);
01745                 }
01746             }
01747         }
01748     }
01749   return 0;
01750 }
01751 
01752 //get the attribute id of a globally declared attribute
01753 Attribute*
01754 SchemaParser::getAttribute(const Qname & attribute)
01755 {
01756   std::string typens = attribute.getNamespace();
01757   if (typens.empty())
01758     typens = tnsUri_;
01759   
01760   if (typens == tnsUri_ || typens == Schema::SchemaUri) {
01761     //check if it is a global attribute
01762     for(std::list<Attribute>::iterator ali=lAttributes_.begin();
01763         ali!=lAttributes_.end();
01764         ali++)
01765       if (ali->getName() == attribute.getLocalName())
01766         return &(*ali);
01767   }else {
01768     //search imported namespaces
01769     for (size_t i = 0; i < importedSchemas_.size(); i++)
01770       {
01771         if ( importedSchemas_[i].ns == typens)
01772           {
01773             if(importedSchemas_[i].sParser )
01774               {
01775                 return importedSchemas_[i].sParser->getAttribute(attribute);
01776               }
01777           }
01778       }
01779   }
01780   return 0;
01781 }
01782 
01783 //get the element id of a globally declared element
01784 Group*
01785 SchemaParser::getGroup(const Qname & name)
01786 {
01787   std::string typens = name.getNamespace();
01788   if (typens.empty())
01789     typens = tnsUri_;
01790   if (typens== tnsUri_ || typens == Schema::SchemaUri)
01791     {
01792 
01793       //check if it is a global group
01794       for (std::list<Group>::iterator gli =lGroups_.begin();
01795            gli!= lGroups_.end();
01796            gli++)
01797         if (gli->getName() == name.getLocalName())
01798           return &(*gli);
01799       return 0;
01800     }
01801   else
01802     { //search imported namespaces
01803       for (size_t i = 0; i < importedSchemas_.size(); i++)
01804         {
01805           if ( importedSchemas_[i].ns == typens)
01806             {
01807               if(importedSchemas_[i].sParser )
01808                 {
01809                   return importedSchemas_[i].sParser->getGroup(name);
01810                 }
01811             }
01812         }
01813     }
01814   return 0;
01815 }
01816 
01817 AttributeGroup*
01818 SchemaParser::getAttributeGroup(const Qname & name)
01819 {
01820   std::string typens = name.getNamespace();
01821   if (typens.empty())
01822     typens = tnsUri_;
01823   if (typens== tnsUri_ || typens == Schema::SchemaUri)
01824     {
01825 
01826       //check if it is a global group
01827        for (AttributeGroupList::iterator agli = lAttributeGroups_.begin();
01828             agli!= lAttributeGroups_.end();
01829             agli++)
01830         if ((*agli)->getName() == name.getLocalName())
01831           return (*agli);
01832       return 0;
01833     }
01834   else
01835     { //search imported namespaces
01836       for (size_t i = 0; i < importedSchemas_.size(); i++)
01837         {
01838           if ( importedSchemas_[i].ns == typens)
01839             {
01840               if(importedSchemas_[i].sParser )
01841                 {
01842                   return importedSchemas_[i].sParser->getAttributeGroup(name);
01843                 }
01844             }
01845         }
01846     }
01847   return 0;
01848 }
01849 
01850 std::string
01851 SchemaParser::getNamespace(void) const
01852 {
01853   return tnsUri_;
01854 }
01855 
01856 
01857 const XSDType *
01858 SchemaParser::getType(int id) const
01859 {
01860   return (const XSDType *) typesTable_.getTypePtr(id);
01861 }
01862 
01863 
01864 const XSDType *
01865 SchemaParser::getType(const Qname & type ) 
01866 {
01867   int id;
01868   Qname t=type;
01869   
01870   if((id=getTypeId(t,false))==0)
01871     return 0;
01872   else
01873     return (const XSDType *) typesTable_.getTypePtr(id);
01874 }
01875 
01876 
01877   const XSDType *
01878     SchemaParser::getType(int id, std::string &nameSpace)
01879   {
01880     const SchemaParser *sp = getImportedSchema(nameSpace);
01881     if (sp == NULL)
01882     {
01883       return 0;
01884     }
01885     else
01886     {
01887       return sp->getType(id);
01888     }
01889   }
01890 
01891   const SchemaParser *
01892     SchemaParser::getImportedSchema(std::string &nameSpace)
01893   {
01894     if (nameSpace.empty()|| nameSpace == tnsUri_ || nameSpace == Schema::SchemaUri)    
01895     {
01896       return this;
01897     }
01898 
01899     for (size_t i = 0; i < importedSchemas_.size(); i++) 
01900     {
01901       if ( importedSchemas_[i].ns == nameSpace) 
01902       {
01903         return importedSchemas_[i].sParser;
01904       }
01905     }
01906     return NULL;
01907   }
01908 
01909 list < const XSDType *>*
01910 SchemaParser::getAllTypes() const
01911 {
01912   list < const XSDType *>*pLTypes = new list < const XSDType * >;
01913   for (int i = 0; i < getNumTypes(); i++)
01914     {
01915       const XSDType *pType = getType(i + Schema::XSD_ANYURI + 1);
01916       pLTypes->push_back(pType);
01917     }
01918   return pLTypes;
01919 }
01920 
01921 
01922 int
01923 SchemaParser::getNumTypes() const
01924 {
01925   return typesTable_.getNumTypes();
01926 }
01927 
01928 
01929 int
01930 SchemaParser::getNumElements() const
01931 {
01932   return lElems_.size();
01933 }
01934 
01935 
01936 int
01937 SchemaParser::getNumAttributes() const
01938 {
01939   return lAttributes_.size();
01940 }
01941 
01942 //To be deprecated
01943 bool
01944 SchemaParser::addImports(const std::vector<SchemaParser *> & schemaParsers)
01945 {
01946   for (size_t i=0;i<schemaParsers.size() ;i++){
01947       
01948     if(schemaParsers[i]->getNamespace()!=tnsUri_){
01949         
01950       addImport(schemaParsers[i]);
01951     }
01952   }
01953   return true;
01954 }
01955 
01956 bool 
01957 SchemaParser::addImport(SchemaParser *sp)
01958 {
01959   //check if the namespace is added in the import list
01960   int i= checkImport(sp->getNamespace());
01961   //  std::cout<<"Copying imports to "<<sp->tnsUri_<<std::endl;
01962   //  sp->copyImports(this);
01963   if(i>=0) {
01964     importedSchemas_[i].sParser=sp;
01965     importedSchemas_[i].ns=sp->getNamespace();    
01966   }
01967   else {
01968     //if this was a new import increment
01969     ImportedSchema imp;
01970     imp.sParser=sp;
01971     imp.ns=sp->getNamespace();
01972     importedSchemas_.push_back(imp);
01973   }
01974   return true;
01975 }
01976 
01977 void
01978 SchemaParser::copyImports(SchemaParser * sp)
01979 {
01980   for(size_t i=0;i<importedSchemas_.size();i++) {
01981     
01982     if (importedSchemas_[i].sParser) 
01983       sp->addImport(importedSchemas_[i].sParser);
01984   }
01985 }
01986 
01987 int 
01988 SchemaParser::checkImport(std::string nsp)const
01989 {
01990   for(size_t i=0;i<importedSchemas_.size();i++)
01991     {
01992       if(importedSchemas_[i].ns==nsp)
01993         return i;
01994     }
01995   return -1;
01996 }
01997 
01998 bool 
01999 SchemaParser::addImport(std::string ns,
02000                         std::string location)
02001 {
02002 
02003   int i= checkImport(ns);
02004   if(i==-1) {
02005     ImportedSchema imp;
02006     imp.sParser=0;
02007     imp.ns=ns;
02008     importedSchemas_.push_back(imp);
02009     i =importedSchemas_.size()-1;
02010   }else {
02011     return true;
02012   }
02013 
02014   if(location.empty())
02015     return true;
02016   std::string xsdFile;
02017   if(XmlUtils::fetchUri(location,xsdFile))
02018     {
02019       /*
02020        * If the schema definition was retrieved successfully 
02021        * process it and add it to list of imported schemas
02022        */
02023       SchemaParser *sp = new SchemaParser(xsdFile,ns);
02024       sp->setUri(uri_);
02025       if(sp->parseSchemaTag())
02026         {
02027           importedSchemas_[i].sParser=sp;
02028           return true;
02029         }
02030       else return false;
02031     }
02032   else return false;
02033 
02034 }
02035 
02036 
02037 void SchemaParser::error(std::string mesg, int level)
02038 {
02039   
02040   if (level == 0) {
02041     
02042     SchemaParserException spe(mesg + "\nFatal Error in SchemaParser\n");
02043     spe.line = xParser_->getLineNumber();
02044     spe.col = xParser_->getColumnNumber();
02045     throw spe;
02046   }
02047 
02048   else if (level_ >=1 && level == 1){
02049 
02050     logFile_ << "Error @" << xParser_->
02051       getLineNumber() << ":" << xParser_->
02052       getColumnNumber() << XmlUtils::dbsp << mesg << endl;
02053   }
02054   else if (level_ >= 2 && level == 2) {
02055 
02056     logFile_ << "Alert @" << xParser_->
02057       getLineNumber() << ":" << xParser_->
02058       getColumnNumber() << XmlUtils::dbsp << mesg << endl;
02059 
02060   }
02061 }
02062 
02063 
02064 int
02065 SchemaParser::getBasicContentType(int typeId)const
02066 {
02067   const XSDType *pType = getType(typeId);
02068   int id = typeId;
02069   if (pType != 0) {
02070     
02071     /* 
02072        It could be a complex type with
02073        simple content or a schema defined simpleType
02074     */
02075     if (pType->isSimple() == false){
02076 
02077       const ComplexType * cType= static_cast<const ComplexType*> (pType);
02078 
02079       if(cType->getContentModel()==Schema::Simple){
02080         
02081         id = cType->getContentType();
02082       }
02083       else {
02084         
02085         return Schema::XSD_INVALID;
02086       }
02087     }
02088     else{
02089       
02090       id = (static_cast<const SimpleType *>(pType))->getBaseTypeId();
02091     }
02092     id = getBasicContentType(id);
02093   }
02094   return id;
02095 }
02096 
02097 std::string
02098 SchemaParser::getTypeName(Schema::Type t)const
02099 {
02100   if (isBasicType(t)){
02101     return typesTable_.getAtomicTypeName(t);
02102   }
02103   else {
02104     const XSDType * pType = (const XSDType *) typesTable_.getTypePtr(t);
02105     if (pType)
02106       return pType->getName();
02107   }
02108   return "";
02109 }
02110 
02111 
02112 //handle soap arrays .this is really a special case.more like a hack
02113 bool
02114 SchemaParser::makeListFromSoapArray (ComplexType * ct)
02115 {
02116   const XSDType * baseType=getType(ct->getBaseTypeId());
02117   if (baseType) {
02118     if(baseType->getNamespace()== "http://schemas.xmlsoap.org/soap/encoding/" && 
02119        baseType->getName()=="Array"){
02120       
02121       const Attribute* a = ct->getAttribute("arrayType");
02122       if (!a)
02123         return false;
02124       
02125       std::string array = a->defaultVal();
02126       Qname q(array);
02127       array = q.getLocalName();
02128       while (array[array.length()-1] ==']' && 
02129              array[array.length()-2] =='[')
02130         array = array.substr(0,array.length()-2);
02131 
02132       std::string arrayNs = xParser_->getNamespace(q.getPrefix());
02133       q = Qname(array);
02134       q.setNamespace(arrayNs);
02135       Schema::Type t = (Schema::Type)getTypeId(q,true);
02136           Element e("*",tnsUri_,tnsUri_,t,0,UNBOUNDED);
02137       if (ct->getContents() == 0){
02138         ContentModel * cm = new ContentModel(Schema::Sequence);
02139         ct->setContents(cm);
02140       }
02141       ct->getContents()->addElement(e);
02142       return true;
02143     }
02144   }
02145   return false;
02146 }
02147 }

Generated on Sat May 3 16:28:59 2008 for wsdlpull by  doxygen 1.4.6