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

Generated by  doxygen 1.6.2