wsdlpull 1.23
|
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 }