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         return 0;
00152     }
00153   else
00154     {
00155       /*
00156         Create and return a Type Container
00157         Sometimes elements have multiple occurrences 
00158         in that case incrememnt Containers::num
00159       */
00160       cs = particleContainers_[elemName];
00161       if (!cs)
00162         {
00163           cs = new Containers;
00164           cs->count = cs->num = 0;
00165           particleContainers_[elemName] = cs;
00166         }
00167 
00168           
00169       ContentModel::ContentsIterator cit_b=cm_->begin();
00170       ContentModel::ContentsIterator cit_e=cm_->end();
00171       ContentModel::ContentsIterator ci=cit_b;
00172       
00173       for (ci=cit_b;ci!=cit_e;ci++){
00174         if(ci->second==ContentModel::Particle){
00175           if(ci->first.e->getName()==elemName){
00176             
00177             tC = new TypeContainer (ci->first.e->getType(),
00178                                     sParser_);
00179             tcTable.push_back(tC);
00180             break;
00181           }
00182         }
00183       }
00184       cs->tc.push_back(tC);
00185       cs->num++;
00186       return tC;
00187     }
00188 }
00189 
00190 TypeContainer *
00191 TypeContainer::getBaseTypeContainer(bool create)
00192 {
00193   if (! baseContainer_ && create){
00194 
00195     const XSDType * t = sParser_->getType(typeId_);
00196     if (t->getBaseTypeId() == Schema::XSD_ANYTYPE)
00197       return 0;
00198     baseContainer_ = new TypeContainer(t->getBaseTypeId(),sParser_);
00199   }
00200   return baseContainer_;
00201 }
00202 
00203 TypeContainer *
00204 TypeContainer::getChildContainer(ContentModel* cm ,
00205                                  bool create)
00206 {
00207 
00208   TypeContainer *tC = 0;
00209   if(!create)
00210     {
00211       return cmContainers_[cm];
00212     }
00213   else
00214     {
00215       /*
00216         Create and return a Type Container
00217       */
00218       tC= cmContainers_[cm];
00219       if (!tC)
00220         {
00221           tC= new TypeContainer(cm,sParser_);
00222           cmContainers_[cm]=tC;
00223           tcTable.push_back(tC);
00224         }
00225       return tC;
00226     }
00227 }
00228 
00229 
00230 void *
00231 TypeContainer::getValue()
00232 {
00233   if(!Value.sValue)
00234     return 0; 
00235   
00236   int id = sParser_->getBasicContentType(typeId_);
00237   if(id==0)
00238     return 0;
00239 
00240   switch (id)
00241     {
00242 
00243     case Schema::XSD_INT:
00244     case Schema::XSD_INTEGER:
00245       return (void *) Value.iValue;
00246     case Schema::XSD_LONG:
00247       return (void *) Value.lValue;
00248     case Schema::XSD_POSINT:
00249     case Schema::XSD_ULONG:
00250       return (void *) Value.ulValue;
00251     case Schema::XSD_FLOAT:
00252       return (void *) Value.fValue;
00253     case Schema::XSD_DOUBLE:
00254     case Schema::XSD_DECIMAL:
00255       return (void *) Value.dbValue;
00256     case Schema::XSD_BOOLEAN:
00257       return (void *) Value.bValue;
00258     case Schema::XSD_QNAME:
00259       return (void *) Value.qnValue;
00260     default:
00261       return (void *) Value.sValue;
00262 
00263     }
00264 }
00265 
00266 const SchemaParser *
00267 TypeContainer::schemaParser() const
00268 {
00269       return sParser_;
00270 };
00271 
00272 void
00273 TypeContainer::deleteValue()
00274 {
00275   if(!Value.sValue)
00276     return;
00277 
00278   int id = sParser_->getBasicContentType(typeId_);
00279   if(id==0 || id == Schema::XSD_INVALID)
00280     return ;
00281 
00282   switch (id)
00283     {
00284 
00285     case Schema::XSD_INT:
00286     case Schema::XSD_INTEGER:
00287       delete  Value.iValue;
00288       break;
00289     case Schema::XSD_LONG:
00290        delete Value.lValue;
00291       break;
00292     case Schema::XSD_POSINT:
00293     case Schema::XSD_ULONG:
00294        delete Value.ulValue;
00295       break;
00296     case Schema::XSD_FLOAT:
00297        delete Value.fValue;
00298        break;
00299     case Schema::XSD_DOUBLE:
00300     case Schema::XSD_DECIMAL:
00301        delete Value.dbValue;
00302        break;
00303     case Schema::XSD_BOOLEAN:
00304        delete Value.bValue;
00305        break;
00306     case Schema::XSD_QNAME:
00307        delete Value.qnValue;
00308        break;
00309     default:
00310       delete Value.sValue;
00311       break;
00312     }
00313 }
00314 
00315 void
00316 TypeContainer::print(std::ostream &os)
00317 {
00318   if (typeId_ == Schema::XSD_SCHEMA ||
00319       typeId_ == Schema::XSD_ANY)
00320     return ;
00321   
00322   if (baseContainer_)
00323     baseContainer_->print(os);
00324 
00325   if(cm_){
00326     printContentModel(os);
00327   }
00328   else if (typeId_ != Schema::XSD_INVALID){
00329     
00330     if (sParser_->getBasicContentType(typeId_) == Schema::XSD_INVALID ){
00331 
00332       printComplexType(os);
00333     }
00334     else {
00335 
00336       printSimpleType(os);
00337     }
00338   }
00339 }
00340 
00341 std::ostream &operator<<(std::ostream &os, TypeContainer &tc)
00342 {
00343   tc.print(os);
00344   return os;
00345 }
00346 
00347 
00348 
00349 void
00350 TypeContainer::printSimpleType(std::ostream & os)
00351 {
00352   if (!strVal.empty())
00353     os<<strVal;
00354   else{
00355     
00356     int type = sParser_->getBasicContentType(typeId_);
00357     switch(type){
00358     case Schema::XSD_INT:
00359     case Schema::XSD_INTEGER:
00360       os << *((int *) (getValue ()));
00361       break;
00362     case Schema::XSD_LONG:
00363       os << *((long *) (getValue ()));
00364       break;
00365     case Schema::XSD_POSINT:
00366     case Schema::XSD_ULONG:
00367       os << *((unsigned long *) (getValue ()));
00368       break;
00369     case Schema::XSD_FLOAT:
00370       os << *((float *) (getValue ()));
00371       break;
00372     case Schema::XSD_DOUBLE:
00373     case Schema::XSD_DECIMAL:
00374       os << *((double *) (getValue ()));
00375       break;
00376     case Schema::XSD_BOOLEAN:
00377       os << *((bool *) (getValue ()));
00378       break;
00379     case Schema::XSD_QNAME:
00380       {
00381 #ifdef _WIN32 
00382         Qname qn=*((Qname *) (getValue ()));
00383         os<<qn.getPrefix()<<"{"<<qn.getNamespace()<<"}:"<<qn.getLocalName();
00384 #else
00385         os << *((Qname *) (getValue ()));
00386 #endif
00387       }
00388       break;
00389     default:
00390       os << *((std::string *) (getValue ()));
00391       break;
00392     }
00393 
00394   }
00395   if(!isValueValid_)
00396     os<<" -->Invalid value for data type";
00397 }
00398 
00399 
00400 void 
00401 TypeContainer::printComplexType (std::ostream & os)
00402 {
00403   const ComplexType * ct =static_cast<const ComplexType*>(sParser_->getType(typeId_));
00404   TypeContainer * tmp= 0;
00405   for (int i = 0; i < ct->getNumAttributes (); i++) {
00406     
00407     tmp =getAttributeContainer (ct->getAttributeName (i));
00408     
00409     if(tmp){
00410       
00411       os << "@" << ct->getAttributeName (i) << ":";
00412       os<<*tmp<<std::endl;
00413     }
00414   }
00415   
00416   if(ct->getContentModel()==Schema::Simple){
00417     printSimpleType(os);
00418   }
00419   else{
00420 
00421     ContentModel* cm=ct->getContents();
00422     TypeContainer* tmp=getChildContainer(cm);
00423     if(tmp)
00424       os<<*tmp;
00425   }
00426   os<<std::endl;
00427 }
00428 
00429 void
00430 TypeContainer::printContentModel(std::ostream & os)
00431 {
00432   ContentModel* cm=cm_;
00433   ContentModel::ContentsIterator cit_b=cm->begin();
00434   ContentModel::ContentsIterator cit_e=cm->end();
00435   ContentModel::ContentsIterator ci=cit_e;
00436   for (ci=cit_b;ci!=cit_e;ci++){
00437     TypeContainer* tmp=0 ;
00438     if(ci->second==ContentModel::Particle) {
00439         
00440       do{
00441         tmp=getChildContainer (ci->first.e->getName());
00442         if (tmp == 0)
00443           continue;
00444         //if more than one occurences of the element are found then
00445         //the same call will return the successive instances of the element
00446         if( ci->first.e->getName() !="*" && 
00447             TypeContainer::printTypeNames_)
00448           os << ci->first.e->getName() << ":";
00449         
00450         if( sParser_->getBasicContentType(ci->first.e->getType()) == Schema::XSD_INVALID &&
00451             TypeContainer::printTypeNames_) 
00452           os<<std::endl; //if its a complex type ..print the contents in a new line
00453         
00454         os<<*tmp<<std::endl;
00455         
00456       }while (tmp != 0);
00457     }else{
00458       tmp=getChildContainer (ci->first.c);
00459       if(tmp==0)
00460         continue;
00461       os<<*tmp<<std::endl;
00462     }
00463   }
00464 }
00465 
00466 
00467 void
00468 TypeContainer::rewindParticleContainers(std::map < std::string, Containers *> &particleContainers) 
00469 {
00470   Containers *cs;
00471   std::map < std::string, Containers *>::iterator it = particleContainers_.begin();
00472   std::map < std::string, Containers *>::iterator end = particleContainers_.end();
00473   for ( ; it != end; ++it) {
00474     cs = it->second;
00475     cs->count = 0;
00476   }
00477 }
00478 
00479 ///resets the access counters so that all access starts from first child
00480 void
00481 TypeContainer::rewind()
00482 {
00483   
00484   //must be rewound here make sure that we we get all childs
00485   rewindParticleContainers(particleContainers_);
00486 
00487   if (sParser_->isBasicType(sParser_->getBasicContentType(typeId_))) {
00488     //do nothing more than set count of particleContainers_ below
00489   } else if (cm_) {
00490     ContentModel::ContentsIterator ci = cm_->begin();
00491     ContentModel::ContentsIterator cit_e = cm_->end();
00492     for ( ; ci != cit_e; ci++) {
00493       TypeContainer* tmp = 0;
00494       if (ci->second == ContentModel::Particle) {
00495         while ((tmp = getChildContainer(ci->first.e->getName()))) {
00496           tmp->rewind();
00497         }
00498       } else {
00499         tmp = getChildContainer (ci->first.c);
00500         if (tmp) {
00501           tmp->rewind();
00502         }
00503       }
00504     }
00505   } else {
00506     const ComplexType * ct =static_cast<const ComplexType*>(sParser_->getType(typeId_));
00507     ContentModel* cm=ct->getContents();
00508     TypeContainer * tmp;
00509     if (cm && (tmp = getChildContainer(cm)) != 0) {
00510       tmp->rewind();
00511     }
00512   }
00513 
00514   //must be rewound here again to make sure that our position markers are reset
00515   //because getChildContainer increments them
00516   rewindParticleContainers(particleContainers_);
00517 }
00518 
00519 
00520 /*This is a  helper method to get an element instance whose name is 'name'
00521 and is a simple type.The method is recursive and searches the entire xml instance
00522 for example,if the instance is
00523   <address> 
00524       <city>El Dorado</city>
00525       <street>elm</street>
00526       <name>
00527         <firstname>John</firstname>
00528                 <firstname>Jack</firstname>
00529         <lastname>Doe</lastname>
00530       </name>
00531  </address>
00532  calling getValue("lastname",t) will return a void* to the string "Doe" 
00533  Note that if you want to call this method repeatedly you need to 
00534  rewind the typecontainer.
00535  Also getValue() returns only the first instance of the occurrence of 
00536  "name".So in the above example "John" is returned always.
00537  If you want all instances you the complete API of TypeContainer.
00538 */
00539 
00540 void * 
00541 TypeContainer::getValue(const std::string & name,Schema::Type & type)
00542 {
00543 
00544   if(sParser_->isBasicType(sParser_->getBasicContentType(typeId_))
00545      && Value.sValue){
00546     
00547     //simple type
00548     
00549     type = typeId_;
00550     return (void*)Value.sValue;
00551   }
00552   else if (cm_){
00553     
00554     void * val = 0 ;
00555     ContentModel::ContentsIterator cit_b=cm_->begin();
00556     ContentModel::ContentsIterator cit_e=cm_->end();
00557     ContentModel::ContentsIterator ci=cit_e;
00558     for (ci=cit_b;ci!=cit_e;ci++){
00559       TypeContainer* tmp=0 ;
00560       if(ci->second==ContentModel::Particle) {
00561 
00562         tmp=getChildContainer (ci->first.e->getName());
00563         //cout<<ci->first.e->getName()<<std::endl;
00564         if (tmp == 0)
00565       continue;
00566         if (sParser_->isBasicType(sParser_->getBasicContentType(ci->first.e->getType()))){
00567           
00568           if(ci->first.e->getName() == name){
00569              
00570             return tmp->getValue(name,type);
00571           }
00572           else{
00573             
00574             tmp =0;
00575           }
00576         }
00577 
00578       }
00579       else{
00580 
00581         tmp=getChildContainer (ci->first.c);
00582       }
00583       if (tmp == 0)
00584         continue;
00585       val = tmp->getValue(name,type);
00586       if (val)
00587         return val;
00588           
00589     }
00590     return 0;
00591   }
00592   else{
00593     //complex type
00594     const ComplexType * ct =static_cast<const ComplexType*>(sParser_->getType(typeId_));
00595     TypeContainer * tmp= getAttributeContainer (name);
00596     if (tmp){
00597       return tmp->getValue(name,type);
00598     }
00599     
00600     ContentModel* cm=ct->getContents();
00601     if (cm && (tmp=getChildContainer(cm))!=0){
00602       
00603       return tmp->getValue(name,type);
00604     }
00605   }
00606   return 0;
00607 }
00608 
00609 }

Generated on Sun Nov 26 03:04:43 2006 for wsdlpull by  doxygen 1.4.6