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

Generated on Sun Nov 26 03:04:42 2006 for wsdlpull by  doxygen 1.4.6