SchemaParser.cpp

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

Generated by  doxygen 1.6.2