src/schemaparser/SchemaParser.cpp

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

Generated on Sun Aug 10 00:07:39 2008 for wsdlpull by  doxygen 1.4.6