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

Generated on Fri Oct 19 19:34:04 2007 for wsdlpull by  doxygen 1.4.6