wsdlpull  1.23
TypeContainer.cpp
Go to the documentation of this file.
1 /*
2  * wsdlpull- A C++ parser for WSDL (Web services description language)
3  * Copyright (C) 2005-2007 Vivek Krishna
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  *
20  */
21 
23 
24 namespace Schema {
26 
28  const SchemaParser * sp)
29  :typeId_((Schema::Type)id),
30  cm_(0),
31  sParser_(sp),
32  baseContainer_(0),
33  isValueValid_(true)
34 {
40  Value.sValue=0;
41 
42 }
43 
45  const SchemaParser * sp,
46  int typeId)
47  :typeId_((Schema::Type)typeId), //the type of the complex type which uses this content model
48  cm_(cm),
49  sParser_(sp),
50  baseContainer_(0),
51  isValueValid_(false)
52 {
58  Value.sValue=0;
59 
60 }
61 
63 {
64  if (baseContainer_)
65  delete baseContainer_;
66 
67  /*
68  delete all particle containers
69  */
70  for (std::map < std::string, Containers *>::iterator i = particleContainers_.begin();
71  particleContainers_.end() != i; ++i){
72 
73  delete i->second;
74  }
75 
76  if(tcTable.size()>0) {
77 
78  /*
79  delete all sub type containers
80  */
81  for (size_t i = 0; i < tcTable.size(); i++)
82  delete tcTable[i];
83 
84  }
85  else {
86  /*
87  delete the values if it is an atomic type container
88  */
89  deleteValue();
90  }
91 }
92 
95  bool create)
96 {
97  TypeContainer *container = 0;
98  if ((container = attributeContainers_[elemName]) != 0)
99  return container;
100  if (!create)
101  return container;
102 
103  /*
104  Create and return a Type Container
105  */
106  const XSDType *pType = sParser_->getType(typeId_);
107  if (pType != 0 && !pType->isSimple())
108  {
109  ComplexType *cType = (ComplexType *) pType;
110  for (int i = 0; i < cType->getNumAttributes(); i++)
111  {
112  if (cType->getAttributeName(i) == elemName)
113  {
114  container =
115  new TypeContainer(cType->getAttributeType(i), sParser_);
116  tcTable.push_back(container);
117  break;
118  }
119  }
120  }
121  attributeContainers_[elemName] = container;
122  return container;
123 }
124 
125 
127 TypeContainer::getChildContainer(std::string elemName,
128  bool create)
129 {
130  Containers *cs = 0;
131  TypeContainer *tC = 0;
132  if(!create)
133  {
134  /*
135  Each time this method is called the next occurence of
136  the child container is returned .Once all the occurrences
137  of the child container have been accessed ,return 0
138  */
139 
140  if((cs = particleContainers_[elemName]) != 0)
141  {
142 
143  if (cs->count >= cs->num)
144  {
145  cs->count = 0;
146  return 0;
147  }
148  else
149  return cs->tc[cs->count++];
150  }
151  else {
152  //recurse child containers
153  std::vector<TypeContainer*>::iterator iTc=tcTable.begin();
154  while(iTc != tcTable.end()) {
155 
156  tC = (*iTc)->getChildContainer(elemName);
157  if(tC)
158  return tC;
159  iTc++;
160  }
161  return 0;
162  }
163  }
164  else
165  {
166  /*
167  Create and return a Type Container
168  Sometimes elements have multiple occurrences
169  in that case incrememnt Containers::num
170  */
171  cs = particleContainers_[elemName];
172  if (!cs)
173  {
174  cs = new Containers;
175  cs->count = cs->num = 0;
176  particleContainers_[elemName] = cs;
177  }
178 
179 
181  ContentModel::ContentsIterator cit_e=cm_->end();
183 
184  for (ci=cit_b;ci!=cit_e;ci++){
185  if(ci->second==ContentModel::Particle){
186  if(ci->first.e->getName()==elemName){
187 
188  tC = new TypeContainer (ci->first.e->getType(),
189  sParser_);
190  tcTable.push_back(tC);
191  break;
192  }
193  }
194  }
195  cs->tc.push_back(tC);
196  cs->num++;
197  return tC;
198  }
199 }
200 
203 {
204  if (! baseContainer_ && create){
205 
206  const XSDType * t = sParser_->getType(typeId_);
208  return 0;
209  baseContainer_ = new TypeContainer(t->getBaseTypeId(),sParser_);
210  }
211  return baseContainer_;
212 }
213 
216  bool create)
217 {
218 
219  TypeContainer *tC = 0;
220  if(!create)
221  {
222  tC = cmContainers_[cm];
223  if(tC)
224  return tC;
225 
226  //recurse child containers
227  std::vector<TypeContainer*>::iterator iTc=tcTable.begin();
228  while(iTc!=tcTable.end()) {
229 
230  tC = (*iTc)->getChildContainer(cm);
231  if(tC)
232  return tC;
233  iTc++;
234  }
235  return 0;
236  }
237  else
238  {
239  /*
240  Create and return a Type Container
241  */
242  tC= cmContainers_[cm];
243  if (!tC)
244  {
245  tC= new TypeContainer(cm,sParser_,typeId_);
246  cmContainers_[cm]=tC;
247  tcTable.push_back(tC);
248  }
249  return tC;
250  }
251 }
252 
253 
254 void *
256 {
257  if(!Value.sValue)
258  return 0;
259 
260  int id = sParser_->getBasicContentType(typeId_);
261  if(id==0)
262  return 0;
263 
264  switch (id)
265  {
266 
267  case Schema::XSD_INT:
268  case Schema::XSD_INTEGER:
269  return (void *) Value.iValue;
270  case Schema::XSD_LONG:
271  return (void *) Value.lValue;
272  case Schema::XSD_POSINT:
273  case Schema::XSD_ULONG:
274  return (void *) Value.ulValue;
275  case Schema::XSD_FLOAT:
276  return (void *) Value.fValue;
277  case Schema::XSD_DOUBLE:
278  case Schema::XSD_DECIMAL:
279  return (void *) Value.dbValue;
280  case Schema::XSD_BOOLEAN:
281  return (void *) Value.bValue;
282  case Schema::XSD_QNAME:
283  return (void *) Value.qnValue;
284  default:
285  return (void *) Value.sValue;
286 
287  }
288 }
289 
290 const SchemaParser *
292 {
293  return sParser_;
294 };
295 
296 void
297 TypeContainer::deleteValue()
298 {
299  if(!Value.sValue)
300  return;
301 
302  int id = sParser_->getBasicContentType(typeId_);
303  if(id==0 || id == Schema::XSD_INVALID)
304  return ;
305 
306  switch (id)
307  {
308 
309  case Schema::XSD_INT:
310  case Schema::XSD_INTEGER:
311  delete Value.iValue;
312  break;
313  case Schema::XSD_LONG:
314  delete Value.lValue;
315  break;
316  case Schema::XSD_POSINT:
317  case Schema::XSD_ULONG:
318  delete Value.ulValue;
319  break;
320  case Schema::XSD_FLOAT:
321  delete Value.fValue;
322  break;
323  case Schema::XSD_DOUBLE:
324  case Schema::XSD_DECIMAL:
325  delete Value.dbValue;
326  break;
327  case Schema::XSD_BOOLEAN:
328  delete Value.bValue;
329  break;
330  case Schema::XSD_QNAME:
331  delete Value.qnValue;
332  break;
333  default:
334  delete Value.sValue;
335  break;
336  }
337 }
338 
339 void
340 TypeContainer::print(std::ostream &os)
341 {
342  if (typeId_ == Schema::XSD_SCHEMA ||
343  typeId_ == Schema::XSD_ANY)
344  return ;
345 
346  if (baseContainer_)
347  baseContainer_->print(os);
348 
349  if(cm_){
350  printContentModel(os);
351  }
352  else if (typeId_ != Schema::XSD_INVALID){
353 
354  if (sParser_->getBasicContentType(typeId_) == Schema::XSD_INVALID ){
355 
356  printComplexType(os);
357  }
358  else {
359 
360  printSimpleType(os);
361  }
362  }
363 }
364 
365 std::ostream &operator<<(std::ostream &os, TypeContainer &tc)
366 {
367  tc.print(os);
368  return os;
369 }
370 
371 
372 
373 void
374 TypeContainer::printSimpleType(std::ostream & os)
375 {
376  if (!strVal.empty())
377  os<<strVal;
378  else{
379 
380  int type = sParser_->getBasicContentType(typeId_);
381  switch(type){
382  case Schema::XSD_INT:
383  case Schema::XSD_INTEGER:
384  os << *((int *) (getValue ()));
385  break;
386  case Schema::XSD_LONG:
387  os << *((long *) (getValue ()));
388  break;
389  case Schema::XSD_POSINT:
390  case Schema::XSD_ULONG:
391  os << *((unsigned long *) (getValue ()));
392  break;
393  case Schema::XSD_FLOAT:
394  os << *((float *) (getValue ()));
395  break;
396  case Schema::XSD_DOUBLE:
397  case Schema::XSD_DECIMAL:
398  os << *((double *) (getValue ()));
399  break;
400  case Schema::XSD_BOOLEAN:
401  os << *((bool *) (getValue ()));
402  break;
403  case Schema::XSD_QNAME:
404  {
405 #ifdef _WIN32
406  Qname qn=*((Qname *) (getValue ()));
407  os<<qn.getPrefix()<<"{"<<qn.getNamespace()<<"}:"<<qn.getLocalName();
408 #else
409  os << *((Qname *) (getValue ()));
410 #endif
411  }
412  break;
413  default:
414  os << *((std::string *) (getValue ()));
415  break;
416  }
417 
418  }
419  if(!isValueValid_)
420  os<<" -->Invalid value for data type";
421 }
422 
423 
424 void
425 TypeContainer::printComplexType (std::ostream & os)
426 {
427  const ComplexType * ct =static_cast<const ComplexType*>(sParser_->getType(typeId_));
428  TypeContainer * tmp= 0;
429  for (int i = 0; i < ct->getNumAttributes (); i++) {
430 
431  tmp =getAttributeContainer (ct->getAttributeName (i));
432 
433  if(tmp){
434 
435  os << "@" << ct->getAttributeName (i) << ":";
436  os<<*tmp<<std::endl;
437  }
438  }
439 
440  if(ct->getContentModel()==Schema::Simple){
441  printSimpleType(os);
442  }
443  else{
444 
445  ContentModel* cm=ct->getContents();
447  if(tmp)
448  os<<*tmp;
449  }
450  os<<std::endl;
451 }
452 
453 void
454 TypeContainer::printContentModel(std::ostream & os)
455 {
456  ContentModel* cm=cm_;
457  ContentModel::ContentsIterator cit_b=cm->begin();
458  ContentModel::ContentsIterator cit_e=cm->end();
460  for (ci=cit_b;ci!=cit_e;ci++){
461  TypeContainer* tmp=0 ;
462  if(ci->second==ContentModel::Particle) {
463 
464  do{
465  tmp=getChildContainer (ci->first.e->getName());
466  if (tmp == 0)
467  continue;
468  //if more than one occurences of the element are found then
469  //the same call will return the successive instances of the element
470  if( ci->first.e->getName() !="*" &&
472  os << ci->first.e->getName() << ":";
473 
474  if( sParser_->getBasicContentType(ci->first.e->getType()) == Schema::XSD_INVALID &&
476  os<<std::endl; //if its a complex type ..print the contents in a new line
477 
478  os<<*tmp<<std::endl;
479 
480  }while (tmp != 0);
481  }else{
482  tmp=getChildContainer (ci->first.c);
483  if(tmp==0)
484  continue;
485  os<<*tmp<<std::endl;
486  }
487  }
488 }
489 
490 
491 void
492 TypeContainer::rewindParticleContainers(std::map < std::string, Containers *> &particleContainers)
493 {
494  Containers *cs;
495  std::map < std::string, Containers *>::iterator it = particleContainers_.begin();
496  std::map < std::string, Containers *>::iterator end = particleContainers_.end();
497  for ( ; it != end; ++it) {
498  cs = it->second;
499  if(cs)
500  cs->count = 0;
501  }
502 }
503 
505 void
507 {
508 
509  //must be rewound here make sure that we we get all childs
510  rewindParticleContainers(particleContainers_);
511 
512  if (sParser_->isBasicType(sParser_->getBasicContentType(typeId_))) {
513  //do nothing more than set count of particleContainers_ below
514  } else if (cm_) {
516  ContentModel::ContentsIterator cit_e = cm_->end();
517  for ( ; ci != cit_e; ci++) {
518  TypeContainer* tmp = 0;
519  if (ci->second == ContentModel::Particle) {
520  while ((tmp = getChildContainer(ci->first.e->getName()))) {
521  tmp->rewind();
522  }
523  } else {
524  tmp = getChildContainer (ci->first.c);
525  if (tmp) {
526  tmp->rewind();
527  }
528  }
529  }
530  } else {
531  const ComplexType * ct =static_cast<const ComplexType*>(sParser_->getType(typeId_));
532  ContentModel* cm=ct->getContents();
533  TypeContainer * tmp;
534  if (cm && (tmp = getChildContainer(cm)) != 0) {
535  tmp->rewind();
536  }
537  }
538 
539  //must be rewound here again to make sure that our position markers are reset
540  //because getChildContainer increments them
541  rewindParticleContainers(particleContainers_);
542 }
543 
544 
545 /*This is a helper method to get an element instance whose name is 'name'
546 and is a simple type.The method is recursive and searches the entire xml instance
547 for example,if the instance is
548  <address>
549  <city>El Dorado</city>
550  <street>elm</street>
551  <name>
552  <firstname>John</firstname>
553  <firstname>Jack</firstname>
554  <lastname>Doe</lastname>
555  </name>
556  </address>
557  calling getValue("lastname",t) will return a void* to the string "Doe"
558  Note that if you want to call this method repeatedly you need to
559  rewind the typecontainer.
560  Also getValue() returns only the first instance of the occurrence of
561  "name".So in the above example "John" is returned always.
562  If you want all instances you the complete API of TypeContainer.
563 */
564 
565 void *
566 TypeContainer::getValue(const std::string & name,Schema::Type & type)
567 {
568 
569  if(sParser_->isBasicType(sParser_->getBasicContentType(typeId_))
570  && Value.sValue){
571 
572  //simple type
573 
574  type = typeId_;
575  return (void*)Value.sValue;
576  }
577  else if (cm_){
578 
579  void * val = 0 ;
581  ContentModel::ContentsIterator cit_e=cm_->end();
583  for (ci=cit_b;ci!=cit_e;ci++){
584  TypeContainer* tmp=0 ;
585  if(ci->second==ContentModel::Particle) {
586 
587  tmp=getChildContainer (ci->first.e->getName());
588  //cout<<ci->first.e->getName()<<std::endl;
589  if (tmp == 0)
590  continue;
591  if (sParser_->isBasicType(sParser_->getBasicContentType(ci->first.e->getType()))){
592 
593  if(ci->first.e->getName() == name){
594 
595  return tmp->getValue(name,type);
596  }
597  else{
598 
599  tmp =0;
600  }
601  }
602 
603  }
604  else{
605 
606  tmp=getChildContainer (ci->first.c);
607  }
608  if (tmp == 0)
609  continue;
610  val = tmp->getValue(name,type);
611  if (val)
612  return val;
613 
614  }
615  return 0;
616  }
617  else{
618  //complex type
619  const ComplexType * ct =static_cast<const ComplexType*>(sParser_->getType(typeId_));
620  TypeContainer * tmp= getAttributeContainer (name);
621  if (tmp){
622  return tmp->getValue(name,type);
623  }
624 
625  ContentModel* cm=ct->getContents();
626  if (cm && (tmp=getChildContainer(cm))!=0){
627 
628  return tmp->getValue(name,type);
629  }
630  }
631  return 0;
632 }
633 
634 }
int getNumAttributes() const
Definition: ComplexType.h:118
void print(std::ostream &os)
int getBasicContentType(int typeId) const
TypeContainer * getChildContainer(std::string elemName, bool create=false)
std::string getNamespace(void) const
Definition: Qname.h:90
std::ostream & operator<<(std::ostream &os, TypeContainer &tc)
const SchemaParser * schemaParser() const
const XSDType * getType(const Qname &type, bool checkImports=true)
std::string getLocalName(void) const
Definition: Qname.h:76
std::string getPrefix(void) const
Definition: Qname.h:83
Definition: Qname.h:30
std::vector< TypeContainer * > tc
Definition: TypeContainer.h:38
static bool printTypeNames_
Definition: TypeContainer.h:98
ContentModel * getContents() const
Definition: ComplexType.h:155
int getBaseTypeId() const
Definition: XSDType.h:185
ContentsIterator begin()
Definition: ContentModel.h:91
std::string getAttributeName(int index) const
Definition: ComplexType.h:132
TypeContainer * getAttributeContainer(std::string attName, bool create=false)
std::list< ContentHolder >::iterator ContentsIterator
Definition: ContentModel.h:55
Type
Definition: Schema.h:59
ContentsIterator end()
Definition: ContentModel.h:98
bool isBasicType(int sType) const
TypeContainer * getBaseTypeContainer(bool create=false)
virtual bool isSimple() const =0
int getAttributeType(int index)
Definition: ComplexType.h:125
TypeContainer(int typeId, const SchemaParser *sp)
void rewind()
resets the access counters so that all access starts from first child