src/schemaparser/SchemaValidator.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 #include <sstream>
00022 #include "schemaparser/SchemaValidator.h"
00023 using namespace std;
00024 
00025 namespace Schema {
00026 /*
00027   This class validates an incoming Xml instance against a given type
00028   whose schema has been processed by a given SchemaParser instance
00029 
00030 */
00031 SchemaValidator::SchemaValidator(const SchemaParser * sp,
00032                                  std::ostream& os)
00033   :ostr_(os),
00034    sParser_(sp)
00035 {
00036 
00037   
00038 }
00039 
00040 SchemaValidator::~SchemaValidator()
00041 {
00042 }
00043 
00044 
00045 /*
00046   Main entry method for validation
00047   Inputs
00048   1. XmlStream ,xpp.getName() muct return the name of the  type
00049   which must be validated
00050   2. typeId of the type against which this stream must be
00051   validated against
00052   3.An Input type container  (default  0)
00053 */
00054 TypeContainer *
00055 SchemaValidator::validate(XmlPullParser * xpp, 
00056                           int typeId,
00057                           TypeContainer * ipTc)
00058 {
00059   try{  
00060     TypeContainer *t;
00061     string elemName = xpp->getName();
00062     const SchemaParser * s1Parser = sParser_;
00063     int typeId1= typeId;
00064 
00065     if (!ipTc)
00066       t = new TypeContainer(typeId, sParser_);
00067     else
00068       t = ipTc;
00069 
00070 
00071 
00072     if (t->getTypeId() != typeId)
00073       error("Fatal error ,container's type is not same as the validated type",xpp);
00074 
00075     // a schema definition inside an instance
00076     if (typeId == Schema::XSD_SCHEMA){
00077       
00078       SchemaParser * ssParser_ = new SchemaParser(xpp);
00079       if (!ssParser_->parseSchemaTag()){
00080         
00081         return 0;
00082       }
00083       return t;
00084     }
00085 
00086     //ignore ANY
00087     if (typeId == Schema::XSD_ANY){
00088       
00089       xpp->skipSubTree();
00090       return t;
00091     }
00092 
00093     // check if this type belongs to the current schema, if not we need to switch contexts
00094     if (!sParser_->isBasicType(typeId)){
00095       
00096       const XSDType * pType = sParser_->getType(typeId);
00097       
00098       if (sParser_->isImported(pType->getNamespace())) {
00099         
00100         sParser_ = sParser_->getImportedSchemaParser(pType->getNamespace());
00101         typeId = const_cast<SchemaParser*>(sParser_)->getTypeId(pType->getQname());
00102         
00103         t->sParser_ = sParser_;
00104         t->typeId_ = (Schema::Type)typeId;
00105 
00106       }
00107     }
00108 
00109     
00110     if (sParser_->getType(typeId) == 0
00111         || sParser_->getType(typeId)->isSimple()) {
00112 
00113       //simple type validation
00114       string val;
00115       xpp->nextToken();
00116       if (xpp->getEventType() == XmlPullParser::TEXT ||
00117           xpp->getEventType() == XmlPullParser::ENTITY_REF){
00118 
00119         val = xpp->getText();
00120 
00121         xpp->nextToken();
00122         while (xpp->getEventType() == XmlPullParser::ENTITY_REF ||
00123                xpp->getEventType() == XmlPullParser::TEXT){
00124 
00125           val += xpp->getText();
00126           xpp->nextToken();
00127             
00128         }
00129         validate(val, typeId, t,xpp);
00130       }
00131       else{
00132         //text was probably empty,nevertheless create  a type container 
00133         validate(val, typeId, t, xpp);
00134       }
00135       if (xpp->getEventType() == XmlPullParser::END_TAG)
00136         {
00137           if (xpp->getName() != elemName)
00138             error("Syntax error "+elemName,xpp);
00139         }
00140       else
00141         error("Expected a closing tag for " + elemName,xpp);
00142     }
00143     else {
00144 
00145       /*
00146         Perform Validation of Complex types
00147         Check for
00148         1.Is the tag name correct (this has to be right !!)
00149         2.Attributes ,if any should be valid
00150         3.Are there any mandatory (#required) attributes
00151         4. Validate its content model 
00152         6.Return the type container which has the
00153         correctly filled in values
00154 
00155       */
00156       const ComplexType *ct =
00157         static_cast<const ComplexType *>(sParser_->getType(typeId));
00158         
00159       const ComplexType * bt = 0;
00160       TypeContainer * btCnt = 0;
00161       if (ct->getBaseTypeId()!=Schema::XSD_ANYTYPE) {
00162 
00163         bt = static_cast<const ComplexType*>
00164           (sParser_->getType(ct->getBaseTypeId()));
00165         btCnt = t->getBaseTypeContainer(true);
00166       }
00167         
00168       int attcnt = xpp->getAttributeCount();
00169         
00170       for (int i = 0; i < attcnt; i++) {
00171           
00172         std::string attName = xpp->getAttributeName(i);
00173         std::string attVal = xpp->getAttributeValue("", attName);
00174         std::string attNsp = xpp->getAttributeNamespace(i);
00175         if (!attNsp.empty() && attNsp != sParser_->getNamespace())
00176           continue;
00177 
00178         const Attribute*at = 0;
00179         TypeContainer *atCnt = 0;
00180         at = ct->getAttribute(attName);
00181 
00182         if (!at && bt){
00183           at  = bt->getAttribute(attName);
00184           if (at)
00185             atCnt = btCnt->getAttributeContainer(attName, true);
00186         }
00187         else{
00188           atCnt = t->getAttributeContainer(attName, true);
00189         }
00190 
00191         if (!at)
00192           error("Unknown attribute \"" + attName +  "\"",xpp);
00193 
00194         validate(attVal, at->getType(), atCnt, xpp);
00195       }
00196         
00197       //see if some required attributes are missing
00198       checkAttributeOccurence(ct,xpp);
00199       if (bt)
00200         checkAttributeOccurence(bt,xpp);
00201 
00202 
00203       if (ct->getContentModel() == Schema::Simple)
00204         {
00205           //complex types with a simple content model
00206 
00207           string val;
00208           xpp->nextToken();
00209           if (xpp->getEventType() == xpp->TEXT){
00210             val = xpp->getText();
00211             validate(val, ct->getContentType(), t, xpp);
00212             xpp->nextTag();
00213           }
00214           else{
00215             //text was probably empty,nevertheless create  a type container 
00216             validate(val, ct->getContentType(), t, xpp);
00217           }
00218 
00219           if (xpp->getEventType() == XmlPullParser::END_TAG)
00220             {
00221               if (xpp->getName() != elemName)
00222                 error("Syntax error",xpp);
00223             }
00224           else
00225             error("Expected a closing tag for " + elemName,xpp);
00226         }
00227       else if (ct->getContentModel() == Schema::Complex){
00228         //a complex type with complex content model
00229         ContentModel* cm=ct->getContents();
00230         if(cm)
00231           validateContentModel(xpp,
00232                                cm,
00233                                t->getChildContainer(cm,true),
00234                                elemName);
00235         else
00236           xpp->nextTag();
00237       }
00238       else{
00239         // a complex type with mixed content model.no support yet
00240       }
00241     }
00242     typeId = typeId1;
00243     sParser_ = s1Parser;
00244     return t;
00245     
00246   }catch (SchemaParserException spe){
00247     if(xpp){
00248     
00249       spe.line=xpp->getLineNumber();
00250       spe.col=xpp->getColumnNumber();    
00251       throw spe;
00252     }
00253   }
00254   return 0;
00255 }
00256 
00257 TypeContainer*
00258 SchemaValidator::validateContentModel(XmlPullParser * xpp, 
00259                                       ContentModel* cm,
00260                                       TypeContainer * ipTc,
00261                                       const string & elemName,
00262                                       bool nested)
00263 {
00264   ContentModel::ContentsIterator cit_b=cm->begin();
00265   ContentModel::ContentsIterator cit_e=cm->end();
00266   ContentModel::ContentsIterator ci=cit_e;
00267   
00268   for (ci=cit_b;ci!=cit_e;ci++){
00269     if(ci->second==ContentModel::Particle)
00270       ci->first.e->nOccurrences=0;
00271   }
00272   ci=cit_b;
00273   switch (cm->getCompositor()) {
00274     
00275   case Schema::All:
00276     {
00277       do
00278         {
00279           if (!nested)
00280             xpp->nextTag();
00281           if (xpp->getEventType() == XmlPullParser::END_TAG)
00282             {
00283               if (xpp->getName() == elemName)
00284                 break;
00285               while (xpp->getEventType() != XmlPullParser::START_TAG)
00286                 xpp->nextTag();
00287             }
00288           //All cannot have another content model inside like group/choice etc
00289  
00290           if(!findElement(cit_b,cit_e,xpp->getName(),ci))
00291             error("Could not find element " +xpp->getName()+" in "+elemName,xpp);
00292           ci->first.e->nOccurrences++;
00293 
00294           validate(xpp, ci->first.e->getType(),
00295                    ipTc->getChildContainer(ci->first.e->getName(), true));
00296           //ipTc->getChildContainer(xpp->getName(), true));
00297         }
00298       while (true);
00299 
00300       /*
00301         check for occurrence constraints
00302       */
00303       for (ci=cit_b;ci!=cit_e;ci++){
00304         if(ci->second==ContentModel::Particle && 
00305            (ci->first.e->nOccurrences<ci->first.e->getMin()||
00306             ci->first.e->nOccurrences>ci->first.e->getMax()))
00307           error(ci->first.e->getName()+" did not meet occurrence constraints",xpp);
00308       }
00309         
00310       break;
00311     }
00312   case Schema::Sequence:
00313     {
00314       do
00315         {
00316           if (!nested)
00317             xpp->nextTag();
00318             
00319           if(xpp->getEventType() != XmlPullParser::END_TAG){
00320 
00321             //loop through all the contents inside
00322             //the child elements in the content model must be in the same
00323             //order as defined in the <sequence> tag of the schema
00324 
00325 
00326             if(ci->second==ContentModel::Particle &&   //if we validated a particle
00327                xpp->getName()!=ci->first.e->getName() && //if the next particle is different
00328                ci->first.e->getName()!="*") {
00329               
00330               
00331               ci++; // move to the next in the list of contents
00332             }
00333 
00334             //TODO multiple occurrences of a content model like sequence
00335             //cant be validated as yet
00336           }else {
00337               
00338             if (xpp->getName() == elemName)
00339               break;
00340             if(ci==cit_e)
00341               break;
00342             /*      while (xpp->getEventType() != XmlPullParser::START_TAG)
00343                     xpp->nextTag();*/
00344 
00345             while ((xpp->getEventType() != XmlPullParser::START_TAG)&&
00346                    ((xpp->getEventType() != XmlPullParser::END_TAG)||
00347                     (xpp->getName() != elemName)))
00348               xpp->nextTag();
00349           }
00350 
00351           if(ci->second==ContentModel::Container){
00352             
00353             if ((xpp->getEventType() == xpp->END_TAG)&&
00354                 (xpp->getName() == elemName))
00355               break;
00356             validateContentModel(xpp,ci->first.c,
00357                                  ipTc->getChildContainer(ci->first.c,true),
00358                                  elemName,true);
00359             ci++;
00360           }
00361           else{
00362 
00363             if(!findElement(ci,cit_e,xpp->getName(), ci) &&
00364                !cm->anyContents())
00365               error("Could not find element " +xpp->getName()+" in "+elemName,xpp);
00366               
00367             ci->first.e->nOccurrences++;
00368             validate(xpp,ci->first.e->getType(),
00369                      ipTc->getChildContainer(ci->first.e->getName(), true));
00370             //ipTc->getChildContainer(xpp->getName(), true));
00371           }
00372         }
00373       while (true);
00374 
00375       /*
00376         check for occurrence constraints
00377       */
00378       for (ci=cit_b;ci!=cit_e;ci++){
00379         if(ci->second==ContentModel::Particle && 
00380            (ci->first.e->nOccurrences<ci->first.e->getMin()||
00381             ci->first.e->nOccurrences>ci->first.e->getMax()))
00382           error(ci->first.e->getName()+" did not meet occurrence constraints",xpp);
00383       }
00384       break;
00385     }      
00386   case Schema::Choice:
00387     {
00388 
00389       if (!nested)
00390         xpp->nextTag();
00391         
00392         
00393       if(findElement(ci,cit_e,xpp->getName(), ci)) {
00394         
00395         std::string choiceElem = xpp->getName();
00396         do {
00397         //see if one of the choices is a particle and it occurs in the instance
00398         ci->first.e->nOccurrences++;
00399         validate(xpp, ci->first.e->getType(),
00400                  ipTc->getChildContainer(ci->first.e->getName(), true));
00401         xpp->nextTag();
00402         }while(xpp->getName() == choiceElem);
00403         xpp->prevTag();  
00404         break;
00405       } 
00406       else {
00407         //its a choice which has a content model
00408         ci++;
00409       }
00410       if (ci->second == ContentModel::Container){
00411         
00412         try {
00413           validateContentModel(xpp,ci->first.c,
00414                                ipTc->getChildContainer(ci->first.c,true),
00415                                elemName,true);
00416         }
00417         catch (SchemaParserException spe){
00418 
00419           ci++;
00420           //try the other content model
00421           validateContentModel(xpp,ci->first.c,
00422                                ipTc->getChildContainer(ci->first.c,true),
00423                                elemName,true);
00424         }
00425       }
00426       else{
00427         
00428         error("Could not find element " +xpp->getName()+" in "+elemName,xpp);
00429       }
00430          
00431       /*
00432        * Only one of the choices is allowed
00433        */
00434         
00435       /*
00436        * check for occurrence constraints
00437        */
00438       if(ci->second==ContentModel::Particle && 
00439          (ci->first.e->nOccurrences<ci->first.e->getMin()||
00440           ci->first.e->nOccurrences>ci->first.e->getMax()))
00441         error(ci->first.e->getName()+"did not meet occurrence constraints",xpp);
00442       
00443       break;
00444     }
00445   }
00446   /*
00447    * reset occurence ocunters
00448    */
00449   for (ci=cit_b;ci!=cit_e;ci++){
00450     
00451     if(ci->second==ContentModel::Particle)
00452       ci->first.e->nOccurrences=0;
00453   }
00454   return ipTc;
00455 }
00456   
00457 
00458 
00459 /*
00460  *  This method validates all supported simple types
00461  *  Both native atomic types and schema defined 
00462  */
00463 
00464 TypeContainer * 
00465 SchemaValidator::validate(void* value ,
00466                           int typeId,
00467                           TypeContainer * ipTc,
00468                           XmlPullParser * xpp)
00469 {
00470   
00471   int basetype = sParser_->getBasicContentType(typeId);
00472   
00473   const XSDType * pType = sParser_->getType(typeId);
00474   if (pType && !pType->isSimple()){
00475     
00476     return 0;
00477   }
00478   const SimpleType  *st = static_cast<const SimpleType*>(pType);
00479   
00480   //check for the validity of the value
00481   //if available also check against restrictions in the schema
00482 
00483   if (!ipTc)
00484     ipTc = new TypeContainer(typeId, sParser_);
00485 
00486   if (st && (st->isList() || st->isUnion())){
00487             
00488     std::string val = *((std::string*)value);
00489     ipTc->setValue(val,validateListOrUnion(st,val,xpp));
00490     return ipTc;
00491   }
00492   switch (basetype)
00493     {
00494     case Schema::XSD_INTEGER:
00495     case Schema::XSD_INT:
00496       {
00497         int x= *((int*)value);
00498         if (!st) {
00499           ipTc->setValue(x);
00500         }
00501         else{
00502 
00503           ipTc->setValue(x,st->isValidInt(x));
00504         }
00505         break;
00506       }
00507     case Schema::XSD_BYTE:
00508       {
00509         char c= *((char*)value);
00510         ipTc->setValue(c);
00511       }
00512       break;
00513     case Schema::XSD_FLOAT:
00514       {
00515         float f = *((float*)value);
00516         if (!st) {
00517           
00518           ipTc->setValue(f);
00519           
00520         }else{
00521           
00522           ipTc->setValue(f,st->isValidFloat(f));
00523         }
00524         break;
00525       }
00526     case Schema::XSD_DOUBLE:
00527     case Schema::XSD_DECIMAL:
00528       {
00529         double db = *((double*)value);
00530         ipTc->setValue(db);
00531       }
00532       break;
00533     case Schema::XSD_LONG:
00534       {
00535         long l = *((long*)value);
00536         ipTc->setValue(l);
00537       }
00538       break;
00539     case Schema::XSD_POSINT:
00540     case Schema::XSD_ULONG:
00541       {
00542         unsigned long  ul= *((unsigned  long*)value);
00543         ipTc->setValue(ul);
00544       }
00545       break;
00546     case Schema::XSD_BOOLEAN:
00547       {
00548         bool b  = *((bool*)value);
00549         ipTc->setValue(b);
00550         break;
00551       }
00552     case Schema::XSD_QNAME:
00553       {
00554         Qname q  = *((Qname* )value);
00555         ipTc->setValue(q);
00556       }
00557       break;
00558     case Schema::XSD_STRING:
00559     default: 
00560       {
00561         std::string val = *((std::string* )value);
00562         if (!st) {
00563           
00564           ipTc->setValue(val);
00565         }
00566         else{
00567           
00568           ipTc->setValue(val,st->isValidString(val));
00569         }
00570       }
00571       break;
00572     }
00573 
00574   return  ipTc;
00575 }
00576 
00577 /*
00578  *  This method validates all supported simple types
00579  *  Both native atomic types and schema defined 
00580  */
00581 
00582 TypeContainer *
00583 SchemaValidator::validate(const string & val,
00584                           int typeId,
00585                           TypeContainer *ipTc,
00586                           XmlPullParser * xpp)
00587 {
00588 
00589   int basetype = sParser_->getBasicContentType(typeId);
00590   if (basetype == Schema::XSD_INVALID) {
00591     
00592     return 0;
00593   }
00594   
00595   const XSDType * pType = sParser_->getType(typeId);
00596   if (pType && 
00597       !pType->isSimple() && 
00598       pType->getContentModel() != Schema::Simple){
00599     
00600     return 0;
00601   }
00602 
00603   if (pType && !pType->isSimple() && 
00604       pType->getContentModel() ==Schema::Simple) {
00605     //this is a complex type but has a simple content model
00606     
00607     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00608     int contentType = ct->getContentType();
00609     return validate(val,contentType,ipTc,xpp);
00610 
00611   }
00612   const SimpleType  *st = static_cast<const SimpleType*>(pType);
00613   
00614   //check for the validity of the value
00615   //if available also check against restrictions in the schema
00616 
00617   if (!ipTc)
00618     ipTc = new TypeContainer(typeId, sParser_);
00619   ipTc->setValAsString(val);
00620 
00621   while(ipTc->isValueValid()){
00622     
00623     extractSimpleType(val, basetype, ipTc, st, xpp);
00624 
00625     
00626     if(!st || (st && (st->isList() || st->isUnion()))){
00627       
00628       break;
00629       //if we validated an atomic type we are done
00630       //if we just validated a list or union,there is no need 
00631       //to continue checking base types
00632     }
00633 
00634     if (!sParser_->isBasicType(st->getBaseTypeId())){
00635       
00636       st=static_cast<const SimpleType*>(sParser_->getType(st->getBaseTypeId()));
00637     }
00638     else{
00639       st = 0;
00640     }
00641   }
00642   return ipTc;
00643 }
00644 
00645 
00646 void 
00647 SchemaValidator::extractSimpleType(const std::string & val,
00648                                    int basetype,
00649                                    TypeContainer * ipTc,
00650                                    const SimpleType * st,
00651                                    XmlPullParser * xpp)
00652 {
00653 
00654   if (st && (st->isList() || st->isUnion())){
00655             
00656     ipTc->setValue(val,validateListOrUnion(st,val,xpp));
00657     return;
00658   }
00659   
00660   istringstream istr(val);
00661   int x;
00662   double db;
00663   long l;
00664   char c;
00665   unsigned long  ul;
00666   float f;
00667 
00668   switch (basetype)
00669     {
00670     case Schema::XSD_INTEGER:
00671     case Schema::XSD_INT:
00672       {
00673         istr >> x;
00674         if (!st) {
00675           ipTc->setValue(x,!istr.fail());
00676         }
00677         else{
00678 
00679           ipTc->setValue(x,!istr.fail() && st->isValidInt(x));
00680         }
00681         break;
00682       }
00683     case Schema::XSD_BYTE:
00684       istr >> c;
00685       ipTc->setValue(c,!istr.fail());
00686       break;
00687     case Schema::XSD_FLOAT:
00688       {
00689         istr >> f;
00690         if (!st) {
00691           ipTc->setValue(f,!istr.fail());
00692         }else{
00693           ipTc->setValue(f,!istr.fail() && st->isValidFloat(f));
00694         }
00695         break;
00696       }
00697     case Schema::XSD_DOUBLE:
00698     case Schema::XSD_DECIMAL:
00699       istr >> db;
00700       ipTc->setValue(db,!istr.fail());
00701       break;
00702     case Schema::XSD_LONG:
00703       istr >> l;
00704       ipTc->setValue(l,!istr.fail());
00705       break;
00706     case Schema::XSD_POSINT:
00707     case Schema::XSD_ULONG:
00708       istr >> ul;
00709       ipTc->setValue(ul,!istr.fail());
00710       break;
00711     case Schema::XSD_BOOLEAN:
00712       {
00713 
00714         if(val=="true" ||
00715            val=="yes" ||
00716            val=="1")
00717         
00718           ipTc->setValue(true);
00719         else
00720           ipTc->setValue(false);
00721         break;
00722       }
00723     case Schema::XSD_QNAME:
00724       {
00725         Qname q(val);
00726         if (xpp)
00727           q.setNamespace(xpp->getNamespace(q.getPrefix()));
00728         ipTc->setValue(q);
00729         break;
00730       }
00731     case Schema::XSD_STRING:
00732     default: 
00733       {
00734         if (!st) {
00735             
00736           ipTc->setValue(val);
00737         }
00738         else{
00739           if (basetype == Schema::XSD_STRING)
00740             ipTc->setValue(val,st->isValidString(val));
00741           else
00742             ipTc->setValue(val);//other types such as date for which no validation is done
00743         }
00744       }
00745       break;
00746     }
00747 }
00748 
00749 /*
00750  * This function validates a string as a list or union 
00751  * for the simple type 
00752  */
00753 
00754 bool
00755 SchemaValidator::validateListOrUnion(const SimpleType* st,
00756                                      const std::string &val,
00757                                      XmlPullParser * xpp)
00758 {
00759   if (st->isList()){
00760    
00761     size_t s = 0;
00762 
00763     while(s < val.length()){
00764       while(val[s]==' ')s++;
00765       std::string t = val.substr(s,val.find(' ',s)-s);
00766       TypeContainer * tc = validate(t,st->getBaseTypeId(),0,xpp);
00767       if (!(tc && tc->isValueValid()))
00768         return false;
00769       s+=t.length()+1;
00770     }
00771     return true ;
00772   
00773   }else if (st->isUnion()){
00774     
00775     std::list<int>::const_iterator it= st->unionTypes()->begin();
00776     while (it!=st->unionTypes()->end()){
00777       TypeContainer * tc = validate(val,*it,0,xpp);
00778       if (tc && tc->isValueValid())
00779         return true;
00780     }
00781     return false;
00782   }
00783   else{
00784     return false;
00785   }
00786 }
00787 /*
00788  * This function searches for a child element in a complex type 
00789  * The iterator pElem is set to point to the found element
00790  * rewind controls whether a search is to be done by resetting pElem 
00791  * to the begining of the list 
00792  * Returns true if element is found else false 
00793  */
00794 
00795 bool
00796 SchemaValidator::findElement(ContentModel::ContentsIterator start, 
00797                              ContentModel::ContentsIterator end, 
00798                              std::string name,
00799                              ContentModel::ContentsIterator & found)
00800 {
00801   for (ContentModel::ContentsIterator ci=start;
00802        ci!=end;
00803        ci++){
00804     
00805     if(ci->second==ContentModel::Particle){
00806 #ifdef LOGGING   
00807        std::cout<<"Looking for "<<ci->first.e->getName()<<" in   "<<name<<std::endl;
00808 #endif
00809       if(ci->first.e->getName()==name ||
00810          ci->first.e->getName() == "*")//* is  a hack for soap arrays
00811         {
00812           found=ci;
00813           return true;
00814         }
00815     }
00816   }
00817   return false;
00818 }
00819 
00820 void SchemaValidator::error(const std::string& mesg,XmlPullParser* xpp)
00821 {
00822     
00823   SchemaParserException spe(mesg + "\nError validating schema instance\n");
00824   if(xpp){
00825     
00826     spe.line=xpp->getLineNumber();
00827     spe.col=xpp->getColumnNumber();
00828   }
00829   throw spe;
00830 }
00831 
00832 
00833 bool
00834 SchemaValidator::checkAttributeOccurence(const ComplexType* ct ,
00835                                          XmlPullParser* xpp)
00836 {
00837 
00838   if (ct->getNumAttributes() > 0)
00839     {
00840       for (int i = 0; i < ct->getNumAttributes(); i++)
00841         {
00842           const Attribute*at = ct->getAttribute(i);
00843               
00844           /*
00845             Check for the correctness of each attribute
00846           */
00847           string attVal = xpp->getAttributeValue("", at->getName());
00848           if (attVal.empty())
00849             {
00850               if (at->isRequired())
00851                 error("Required attribute \"" + at->getName() +
00852                       "\" missing or empty",xpp);
00853 
00854               else
00855                 continue;
00856             }
00857         }
00858     }
00859   return true;
00860 }
00861 
00862 
00863 
00864 bool
00865 SchemaValidator::instance(const std::string& tag,
00866                           Schema::Type type_id)
00867 
00868 {
00869 
00870   //generate an instance of the given type
00871   std::string nsp = sParser_->getNamespace();
00872   xmlStream_ = new XmlSerializer(ostr_); //xml serializer
00873   
00874   if (!nsp.empty()) 
00875     xmlStream_->setPrefix("s",nsp);
00876   
00877   xmlStream_->setPrefix("xsi",Schema::SchemaInstaceUri);
00878   xmlStream_->startDocument("UTF-8",false);
00879 
00880   return instance1(tag,type_id);
00881 }
00882 
00883 bool
00884 SchemaValidator::instance1(const std::string &tag,
00885                            Schema::Type type_id)
00886 {
00887 
00888   std::string nsp = sParser_->getNamespace();
00889   static bool first = false;
00890   xmlStream_->startTag(nsp,tag);
00891   if (!first){
00892     xmlStream_->attribute("",
00893                           "xmlns",
00894                           nsp);
00895     first = true;
00896   }
00897 
00898 
00899   //  xmlStream_->attribute(Schema::SchemaInstaceUri,
00900   //            "type",
00901   //            "s:"+sParser_->getTypeName(type_id));
00902   const XSDType * pType = sParser_->getType(type_id);
00903 
00904   if ( pType== 0 ||
00905        pType->isSimple()){
00906 
00907     xmlStream_->text(""); //simple content types
00908     
00909   }
00910   else {
00911 
00912     const ComplexType * ct =
00913       static_cast<const ComplexType*>(pType);
00914     
00915     //print attributes if any
00916     if (ct->getNumAttributes() > 0) {
00917       
00918       for (int i = 0; i < ct->getNumAttributes(); i++) {
00919         
00920         const Attribute*at = ct->getAttribute(i);
00921         xmlStream_->attribute(sParser_->getNamespace(),at->getName(),"");
00922       }
00923     }
00924   
00925 
00926     if (ct->getContentModel() == Schema::Simple) {
00927       
00928       xmlStream_->text("");
00929     }
00930     else{
00931 
00932       ContentModel* cm=ct->getContents();
00933       instanceCM(cm);
00934       
00935     }
00936   }
00937   xmlStream_->endTag(nsp,tag);
00938   return  true;
00939 }
00940 
00941 
00942 
00943 
00944 void
00945 SchemaValidator::instanceCM(ContentModel *cm)
00946         
00947 {
00948   
00949   ContentModel::ContentsIterator cit_b=cm->begin();
00950   ContentModel::ContentsIterator cit_e=cm->end();
00951   ContentModel::ContentsIterator ci=cit_b;
00952 
00953   switch (cm->getCompositor())
00954     {
00955     case Schema::All:
00956     case Schema::Sequence:
00957     case Schema::Choice:
00958       {
00959         // a simple logic to start with
00960         // not taking care of all,choice ,sequence as of now
00961         
00962         for (ci=cit_b;ci!=cit_e;ci++){
00963           
00964           if(ci->second==ContentModel::Particle &&
00965              ci->first.e->getMax() > 0){
00966 
00967             const SchemaParser* s1Parser = sParser_;
00968             Schema::Type t=(Schema::Type)ci->first.e->getType();
00969             
00970             if (!ci->first.e->getTypeNamespace().empty() &&
00971                 sParser_->isImported(ci->first.e->getTypeNamespace()) &&
00972                 sParser_->getNamespace() != ci->first.e->getTypeNamespace()) {
00973         
00974               //here the type of the element is defined in another imported schemaparser
00975               //so try to get the pointer.
00976               t = (Schema::Type)sParser_->getType(t)->getTypeId();
00977               sParser_ = sParser_->getImportedSchemaParser(ci->first.e->getTypeNamespace());
00978             }
00979            
00980             instance1(ci->first.e->getName(),t);
00981             sParser_ = s1Parser;
00982           }
00983           else if (ci->second==ContentModel::Container) {
00984             
00985             //nested xsd:sequence inside choice..nested content models
00986             instanceCM(ci->first.c);
00987               
00988           }
00989           else if (ci->second==ContentModel::ParticleGroup){
00990             
00991             //xsd:group inside 
00992             instanceCM(ci->first.g->getContents());
00993                                 
00994           }
00995         }
00996         break;
00997       }
00998     }
00999 }
01000 
01001 }
01002 //TODO validation of <any>
01003 //TODO validation of base64binary,hexBinary
01004 //TODO validation of types derived by extension/restriction of complex types

Generated on Sun Aug 10 00:07:39 2008 for wsdlpull by  doxygen 1.4.6