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

Generated on Sun Aug 5 20:01:33 2007 for wsdlpull by  doxygen 1.4.6