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

Generated on Sun Aug 5 20:01:33 2007 for wsdlpull by  doxygen 1.4.6