src/schemaparser/TypeContainer.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  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public
00016  * License along with this library; if not, write to the Free
00017  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  *
00019  *
00020  */
00021 
00022 #include "schemaparser/TypeContainer.h"
00023 
00024 namespace Schema {
00025 bool TypeContainer::printTypeNames_ = true;
00026 
00027 TypeContainer::TypeContainer(int id, 
00028                              const SchemaParser * sp)
00029   :typeId_((Schema::Type)id),
00030    cm_(0),
00031    sParser_(sp),
00032    baseContainer_(0),
00033    isValueValid_(true)
00034 {
00035   /**
00036    * This is a union so setting one pointer
00037    *  will set all to 0 
00038    */
00039     
00040   Value.sValue=0;
00041   
00042 }
00043 
00044 TypeContainer::TypeContainer(ContentModel* cm,
00045                              const SchemaParser * sp)
00046   :typeId_(Schema::XSD_INVALID),
00047    cm_(cm),
00048    sParser_(sp),
00049    baseContainer_(0),
00050    isValueValid_(false)
00051 {
00052   /**
00053    * This is a union so setting one pointer
00054    *  will set all to 0 
00055    */
00056     
00057   Value.sValue=0;
00058   
00059 }
00060 
00061 TypeContainer::~TypeContainer()
00062 {
00063   if (baseContainer_)
00064     delete baseContainer_;
00065 
00066   /*
00067     delete all particle containers
00068   */
00069   for (std::map < std::string, Containers *>::iterator i = particleContainers_.begin();
00070        particleContainers_.end() != i; ++i){
00071     
00072     delete i->second;
00073   }
00074   
00075   if(tcTable.size()>0) {
00076     
00077     /* 
00078        delete all sub type containers
00079     */
00080     for (size_t i = 0; i < tcTable.size(); i++)
00081       delete tcTable[i];
00082   
00083   }
00084   else {
00085     /* 
00086        delete the values if it is an atomic type container
00087     */
00088     deleteValue();
00089   }
00090 }
00091 
00092 TypeContainer*
00093 TypeContainer::getAttributeContainer(std::string elemName,
00094                                      bool create)
00095 {
00096   TypeContainer *container = 0;
00097   if ((container = attributeContainers_[elemName]) != 0)
00098     return container;
00099   if (!create)
00100     return container;
00101 
00102   /*
00103     Create and return a Type Container
00104   */
00105   const XSDType *pType = sParser_->getType(typeId_);
00106   if (pType != 0 && !pType->isSimple())
00107     {
00108       ComplexType *cType = (ComplexType *) pType;
00109       for (int i = 0; i < cType->getNumAttributes(); i++)
00110         {
00111           if (cType->getAttributeName(i) == elemName)
00112             {
00113               container =
00114                 new TypeContainer(cType->getAttributeType(i), sParser_);
00115               tcTable.push_back(container);
00116               break;
00117             }
00118         }
00119     }
00120   attributeContainers_[elemName] = container;
00121   return container;
00122 }
00123 
00124 
00125 TypeContainer *
00126 TypeContainer::getChildContainer(std::string elemName,
00127                                  bool create)
00128 {
00129   Containers *cs = 0;
00130   TypeContainer *tC = 0;
00131   if(!create)
00132     {
00133       /*
00134         Each time this method is called the next occurence  of
00135         the child container is returned .Once all the occurrences
00136         of the child container have been accessed ,return 0
00137       */
00138       
00139       if((cs = particleContainers_[elemName]) != 0)
00140         {
00141           
00142           if (cs->count >= cs->num)
00143             {
00144               cs->count = 0;
00145               return 0;
00146             }
00147           else
00148             return cs->tc[cs->count++];
00149         }
00150       else {
00151         //recurse child containers
00152         std::vector<TypeContainer*>::iterator iTc=tcTable.begin();
00153         while(iTc != tcTable.end()) {
00154 
00155           tC = (*iTc)->getChildContainer(elemName);
00156           if(tC)
00157             return tC;
00158           iTc++;
00159         }
00160         return 0;
00161       }
00162     }
00163   else
00164     {
00165       /*
00166         Create and return a Type Container
00167         Sometimes elements have multiple occurrences 
00168         in that case incrememnt Containers::num
00169       */
00170       cs = particleContainers_[elemName];
00171       if (!cs)
00172         {
00173           cs = new Containers;
00174           cs->count = cs->num = 0;
00175           particleContainers_[elemName] = cs;
00176         }
00177 
00178           
00179       ContentModel::ContentsIterator cit_b=cm_->begin();
00180       ContentModel::ContentsIterator cit_e=cm_->end();
00181       ContentModel::ContentsIterator ci=cit_b;
00182       
00183       for (ci=cit_b;ci!=cit_e;ci++){
00184         if(ci->second==ContentModel::Particle){
00185           if(ci->first.e->getName()==elemName){
00186             
00187             tC = new TypeContainer (ci->first.e->getType(),
00188                                     sParser_);
00189             tcTable.push_back(tC);
00190             break;
00191           }
00192         }
00193       }
00194       cs->tc.push_back(tC);
00195       cs->num++;
00196       return tC;
00197     }
00198 }
00199 
00200 TypeContainer *
00201 TypeContainer::getBaseTypeContainer(bool create)
00202 {
00203   if (! baseContainer_ && create){
00204 
00205     const XSDType * t = sParser_->getType(typeId_);
00206     if (t->getBaseTypeId() == Schema::XSD_ANYTYPE)
00207       return 0;
00208     baseContainer_ = new TypeContainer(t->getBaseTypeId(),sParser_);
00209   }
00210   return baseContainer_;
00211 }
00212 
00213 TypeContainer *
00214 TypeContainer::getChildContainer(ContentModel* cm ,
00215                                  bool create)
00216 {
00217 
00218   TypeContainer *tC = 0;
00219   if(!create)
00220     {
00221       tC = cmContainers_[cm];
00222       if(tC)
00223         return tC;
00224       
00225         //recurse child containers
00226       std::vector<TypeContainer*>::iterator iTc=tcTable.begin();
00227       while(iTc!=tcTable.end()) {
00228         
00229         tC = (*iTc)->getChildContainer(cm);
00230         if(tC)
00231           return tC;
00232         iTc++;
00233       }
00234       return 0;
00235     }
00236   else
00237     {
00238       /*
00239         Create and return a Type Container
00240       */
00241       tC= cmContainers_[cm];
00242       if (!tC)
00243         {
00244           tC= new TypeContainer(cm,sParser_);
00245           cmContainers_[cm]=tC;
00246           tcTable.push_back(tC);
00247         }
00248       return tC;
00249     }
00250 }
00251 
00252 
00253 void *
00254 TypeContainer::getValue()
00255 {
00256   if(!Value.sValue)
00257     return 0; 
00258   
00259   int id = sParser_->getBasicContentType(typeId_);
00260   if(id==0)
00261     return 0;
00262 
00263   switch (id)
00264     {
00265 
00266     case Schema::XSD_INT:
00267     case Schema::XSD_INTEGER:
00268       return (void *) Value.iValue;
00269     case Schema::XSD_LONG:
00270       return (void *) Value.lValue;
00271     case Schema::XSD_POSINT:
00272     case Schema::XSD_ULONG:
00273       return (void *) Value.ulValue;
00274     case Schema::XSD_FLOAT:
00275       return (void *) Value.fValue;
00276     case Schema::XSD_DOUBLE:
00277     case Schema::XSD_DECIMAL:
00278       return (void *) Value.dbValue;
00279     case Schema::XSD_BOOLEAN:
00280       return (void *) Value.bValue;
00281     case Schema::XSD_QNAME:
00282       return (void *) Value.qnValue;
00283     default:
00284       return (void *) Value.sValue;
00285 
00286     }
00287 }
00288 
00289 const SchemaParser *
00290 TypeContainer::schemaParser() const
00291 {
00292       return sParser_;
00293 };
00294 
00295 void
00296 TypeContainer::deleteValue()
00297 {
00298   if(!Value.sValue)
00299     return;
00300 
00301   int id = sParser_->getBasicContentType(typeId_);
00302   if(id==0 || id == Schema::XSD_INVALID)
00303     return ;
00304 
00305   switch (id)
00306     {
00307 
00308     case Schema::XSD_INT:
00309     case Schema::XSD_INTEGER:
00310       delete  Value.iValue;
00311       break;
00312     case Schema::XSD_LONG:
00313        delete Value.lValue;
00314       break;
00315     case Schema::XSD_POSINT:
00316     case Schema::XSD_ULONG:
00317        delete Value.ulValue;
00318       break;
00319     case Schema::XSD_FLOAT:
00320        delete Value.fValue;
00321        break;
00322     case Schema::XSD_DOUBLE:
00323     case Schema::XSD_DECIMAL:
00324        delete Value.dbValue;
00325        break;
00326     case Schema::XSD_BOOLEAN:
00327        delete Value.bValue;
00328        break;
00329     case Schema::XSD_QNAME:
00330        delete Value.qnValue;
00331        break;
00332     default:
00333       delete Value.sValue;
00334       break;
00335     }
00336 }
00337 
00338 void
00339 TypeContainer::print(std::ostream &os)
00340 {
00341   if (typeId_ == Schema::XSD_SCHEMA ||
00342       typeId_ == Schema::XSD_ANY)
00343     return ;
00344   
00345   if (baseContainer_)
00346     baseContainer_->print(os);
00347 
00348   if(cm_){
00349     printContentModel(os);
00350   }
00351   else if (typeId_ != Schema::XSD_INVALID){
00352     
00353     if (sParser_->getBasicContentType(typeId_) == Schema::XSD_INVALID ){
00354 
00355       printComplexType(os);
00356     }
00357     else {
00358 
00359       printSimpleType(os);
00360     }
00361   }
00362 }
00363 
00364 std::ostream &operator<<(std::ostream &os, TypeContainer &tc)
00365 {
00366   tc.print(os);
00367   return os;
00368 }
00369 
00370 
00371 
00372 void
00373 TypeContainer::printSimpleType(std::ostream & os)
00374 {
00375   if (!strVal.empty())
00376     os<<strVal;
00377   else{
00378     
00379     int type = sParser_->getBasicContentType(typeId_);
00380     switch(type){
00381     case Schema::XSD_INT:
00382     case Schema::XSD_INTEGER:
00383       os << *((int *) (getValue ()));
00384       break;
00385     case Schema::XSD_LONG:
00386       os << *((long *) (getValue ()));
00387       break;
00388     case Schema::XSD_POSINT:
00389     case Schema::XSD_ULONG:
00390       os << *((unsigned long *) (getValue ()));
00391       break;
00392     case Schema::XSD_FLOAT:
00393       os << *((float *) (getValue ()));
00394       break;
00395     case Schema::XSD_DOUBLE:
00396     case Schema::XSD_DECIMAL:
00397       os << *((double *) (getValue ()));
00398       break;
00399     case Schema::XSD_BOOLEAN:
00400       os << *((bool *) (getValue ()));
00401       break;
00402     case Schema::XSD_QNAME:
00403       {
00404 #ifdef _WIN32 
00405         Qname qn=*((Qname *) (getValue ()));
00406         os<<qn.getPrefix()<<"{"<<qn.getNamespace()<<"}:"<<qn.getLocalName();
00407 #else
00408         os << *((Qname *) (getValue ()));
00409 #endif
00410       }
00411       break;
00412     default:
00413       os << *((std::string *) (getValue ()));
00414       break;
00415     }
00416 
00417   }
00418   if(!isValueValid_)
00419     os<<" -->Invalid value for data type";
00420 }
00421 
00422 
00423 void 
00424 TypeContainer::printComplexType (std::ostream & os)
00425 {
00426   const ComplexType * ct =static_cast<const ComplexType*>(sParser_->getType(typeId_));
00427   TypeContainer * tmp= 0;
00428   for (int i = 0; i < ct->getNumAttributes (); i++) {
00429     
00430     tmp =getAttributeContainer (ct->getAttributeName (i));
00431     
00432     if(tmp){
00433       
00434       os << "@" << ct->getAttributeName (i) << ":";
00435       os<<*tmp<<std::endl;
00436     }
00437   }
00438   
00439   if(ct->getContentModel()==Schema::Simple){
00440     printSimpleType(os);
00441   }
00442   else{
00443 
00444     ContentModel* cm=ct->getContents();
00445     TypeContainer* tmp=getChildContainer(cm);
00446     if(tmp)
00447       os<<*tmp;
00448   }
00449   os<<std::endl;
00450 }
00451 
00452 void
00453 TypeContainer::printContentModel(std::ostream & os)
00454 {
00455   ContentModel* cm=cm_;
00456   ContentModel::ContentsIterator cit_b=cm->begin();
00457   ContentModel::ContentsIterator cit_e=cm->end();
00458   ContentModel::ContentsIterator ci=cit_e;
00459   for (ci=cit_b;ci!=cit_e;ci++){
00460     TypeContainer* tmp=0 ;
00461     if(ci->second==ContentModel::Particle) {
00462         
00463       do{
00464         tmp=getChildContainer (ci->first.e->getName());
00465         if (tmp == 0)
00466           continue;
00467         //if more than one occurences of the element are found then
00468         //the same call will return the successive instances of the element
00469         if( ci->first.e->getName() !="*" && 
00470             TypeContainer::printTypeNames_)
00471           os << ci->first.e->getName() << ":";
00472         
00473         if( sParser_->getBasicContentType(ci->first.e->getType()) == Schema::XSD_INVALID &&
00474             TypeContainer::printTypeNames_) 
00475           os<<std::endl; //if its a complex type ..print the contents in a new line
00476         
00477         os<<*tmp<<std::endl;
00478         
00479       }while (tmp != 0);
00480     }else{
00481       tmp=getChildContainer (ci->first.c);
00482       if(tmp==0)
00483         continue;
00484       os<<*tmp<<std::endl;
00485     }
00486   }
00487 }
00488 
00489 
00490 void
00491 TypeContainer::rewindParticleContainers(std::map < std::string, Containers *> &particleContainers) 
00492 {
00493   Containers *cs;
00494   std::map < std::string, Containers *>::iterator it = particleContainers_.begin();
00495   std::map < std::string, Containers *>::iterator end = particleContainers_.end();
00496   for ( ; it != end; ++it) {
00497     cs = it->second;
00498     if(cs)
00499       cs->count = 0;
00500   }
00501 }
00502 
00503 ///resets the access counters so that all access starts from first child
00504 void
00505 TypeContainer::rewind()
00506 {
00507   
00508   //must be rewound here make sure that we we get all childs
00509   rewindParticleContainers(particleContainers_);
00510 
00511   if (sParser_->isBasicType(sParser_->getBasicContentType(typeId_))) {
00512     //do nothing more than set count of particleContainers_ below
00513   } else if (cm_) {
00514     ContentModel::ContentsIterator ci = cm_->begin();
00515     ContentModel::ContentsIterator cit_e = cm_->end();
00516     for ( ; ci != cit_e; ci++) {
00517       TypeContainer* tmp = 0;
00518       if (ci->second == ContentModel::Particle) {
00519         while ((tmp = getChildContainer(ci->first.e->getName()))) {
00520           tmp->rewind();
00521         }
00522       } else {
00523         tmp = getChildContainer (ci->first.c);
00524         if (tmp) {
00525           tmp->rewind();
00526         }
00527       }
00528     }
00529   } else {
00530     const ComplexType * ct =static_cast<const ComplexType*>(sParser_->getType(typeId_));
00531     ContentModel* cm=ct->getContents();
00532     TypeContainer * tmp;
00533     if (cm && (tmp = getChildContainer(cm)) != 0) {
00534       tmp->rewind();
00535     }
00536   }
00537 
00538   //must be rewound here again to make sure that our position markers are reset
00539   //because getChildContainer increments them
00540   rewindParticleContainers(particleContainers_);
00541 }
00542 
00543 
00544 /*This is a  helper method to get an element instance whose name is 'name'
00545 and is a simple type.The method is recursive and searches the entire xml instance
00546 for example,if the instance is
00547   <address> 
00548       <city>El Dorado</city>
00549       <street>elm</street>
00550       <name>
00551         <firstname>John</firstname>
00552                 <firstname>Jack</firstname>
00553         <lastname>Doe</lastname>
00554       </name>
00555  </address>
00556  calling getValue("lastname",t) will return a void* to the string "Doe" 
00557  Note that if you want to call this method repeatedly you need to 
00558  rewind the typecontainer.
00559  Also getValue() returns only the first instance of the occurrence of 
00560  "name".So in the above example "John" is returned always.
00561  If you want all instances you the complete API of TypeContainer.
00562 */
00563 
00564 void * 
00565 TypeContainer::getValue(const std::string & name,Schema::Type & type)
00566 {
00567 
00568   if(sParser_->isBasicType(sParser_->getBasicContentType(typeId_))
00569      && Value.sValue){
00570     
00571     //simple type
00572     
00573     type = typeId_;
00574     return (void*)Value.sValue;
00575   }
00576   else if (cm_){
00577     
00578     void * val = 0 ;
00579     ContentModel::ContentsIterator cit_b=cm_->begin();
00580     ContentModel::ContentsIterator cit_e=cm_->end();
00581     ContentModel::ContentsIterator ci=cit_e;
00582     for (ci=cit_b;ci!=cit_e;ci++){
00583       TypeContainer* tmp=0 ;
00584       if(ci->second==ContentModel::Particle) {
00585 
00586         tmp=getChildContainer (ci->first.e->getName());
00587         //cout<<ci->first.e->getName()<<std::endl;
00588         if (tmp == 0)
00589       continue;
00590         if (sParser_->isBasicType(sParser_->getBasicContentType(ci->first.e->getType()))){
00591           
00592           if(ci->first.e->getName() == name){
00593              
00594             return tmp->getValue(name,type);
00595           }
00596           else{
00597             
00598             tmp =0;
00599           }
00600         }
00601 
00602       }
00603       else{
00604 
00605         tmp=getChildContainer (ci->first.c);
00606       }
00607       if (tmp == 0)
00608         continue;
00609       val = tmp->getValue(name,type);
00610       if (val)
00611         return val;
00612           
00613     }
00614     return 0;
00615   }
00616   else{
00617     //complex type
00618     const ComplexType * ct =static_cast<const ComplexType*>(sParser_->getType(typeId_));
00619     TypeContainer * tmp= getAttributeContainer (name);
00620     if (tmp){
00621       return tmp->getValue(name,type);
00622     }
00623     
00624     ContentModel* cm=ct->getContents();
00625     if (cm && (tmp=getChildContainer(cm))!=0){
00626       
00627       return tmp->getValue(name,type);
00628     }
00629   }
00630   return 0;
00631 }
00632 
00633 }

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