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("Unknown 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             //loop through all the contents inside
00298             //the child elements in the content model must be in the same
00299             //order as defined in the <sequence> tag of the schema
00300 
00301 
00302             if(ci->second==ContentModel::Particle &&   //if we validated a particle
00303                xpp->getName()!=ci->first.e->getName() && //if the next particle is different
00304                ci->first.e->getName()!="*") {
00305               
00306               
00307               ci++; // move to the next in the list of contents
00308             }
00309 
00310             //TODO multiple occurrences of a content model like sequence
00311             //cant be validated as yet
00312           }else {
00313               
00314             if (xpp->getName() == elemName)
00315               break;
00316             if(ci==cit_e)
00317               break;
00318             /*      while (xpp->getEventType() != XmlPullParser::START_TAG)
00319                     xpp->nextTag();*/
00320 
00321             while ((xpp->getEventType() != XmlPullParser::START_TAG)&&
00322                    ((xpp->getEventType() != XmlPullParser::END_TAG)||
00323                     (xpp->getName() != elemName)))
00324               xpp->nextTag();
00325           }
00326 
00327           if(ci->second==ContentModel::Container){
00328             
00329             if ((xpp->getEventType() == xpp->END_TAG)&&
00330                 (xpp->getName() == elemName))
00331               break;
00332             validateContentModel(xpp,ci->first.c,
00333                                  ipTc->getChildContainer(ci->first.c,true),
00334                                  elemName,true);
00335             ci++;
00336           }
00337           else{
00338 
00339             if(!findElement(ci,cit_e,xpp->getName(), ci) &&
00340                !cm->anyContents())
00341               error("Could not find element " +xpp->getName()+" in "+elemName,xpp);
00342               
00343             ci->first.e->nOccurrences++;
00344             validate(xpp,ci->first.e->getType(),
00345                      ipTc->getChildContainer(ci->first.e->getName(), true));
00346             //ipTc->getChildContainer(xpp->getName(), true));
00347           }
00348         }
00349       while (true);
00350 
00351       /*
00352         check for occurrence constraints
00353       */
00354       for (ci=cit_b;ci!=cit_e;ci++){
00355         if(ci->second==ContentModel::Particle && 
00356            (ci->first.e->nOccurrences<ci->first.e->getMin()||
00357             ci->first.e->nOccurrences>ci->first.e->getMax()))
00358           error(ci->first.e->getName()+" did not meet occurrence constraints",xpp);
00359       }
00360       break;
00361     }      
00362   case Schema::Choice:
00363     {
00364 
00365       if (!nested)
00366         xpp->nextTag();
00367         
00368         
00369       if(findElement(ci,cit_e,xpp->getName(), ci)) {
00370         
00371         std::string choiceElem = xpp->getName();
00372         do {
00373         //see if one of the choices is a particle and it occurs in the instance
00374         ci->first.e->nOccurrences++;
00375         validate(xpp, ci->first.e->getType(),
00376                  ipTc->getChildContainer(ci->first.e->getName(), true));
00377         xpp->nextTag();
00378         }while(xpp->getName() == choiceElem);
00379         xpp->prevTag();  
00380         break;
00381       } 
00382       else {
00383         //its a choice which has a content model
00384         ci++;
00385       }
00386       if (ci->second == ContentModel::Container){
00387         
00388         try {
00389           validateContentModel(xpp,ci->first.c,
00390                                ipTc->getChildContainer(ci->first.c,true),
00391                                elemName,true);
00392         }
00393         catch (SchemaParserException spe){
00394 
00395           ci++;
00396           //try the other content model
00397           validateContentModel(xpp,ci->first.c,
00398                                ipTc->getChildContainer(ci->first.c,true),
00399                                elemName,true);
00400         }
00401       }
00402       else{
00403         
00404         error("Could not find element " +xpp->getName()+" in "+elemName,xpp);
00405       }
00406          
00407       /*
00408        * Only one of the choices is allowed
00409        */
00410         
00411       /*
00412        * check for occurrence constraints
00413        */
00414       if(ci->second==ContentModel::Particle && 
00415          (ci->first.e->nOccurrences<ci->first.e->getMin()||
00416           ci->first.e->nOccurrences>ci->first.e->getMax()))
00417         error(ci->first.e->getName()+"did not meet occurrence constraints",xpp);
00418       
00419       break;
00420     }
00421   }
00422   /*
00423    * reset occurence ocunters
00424    */
00425   for (ci=cit_b;ci!=cit_e;ci++){
00426     
00427     if(ci->second==ContentModel::Particle)
00428       ci->first.e->nOccurrences=0;
00429   }
00430   return ipTc;
00431 }
00432   
00433 
00434 
00435 /*
00436  *  This method validates all supported simple types
00437  *  Both native atomic types and schema defined 
00438  */
00439 
00440 TypeContainer * 
00441 SchemaValidator::validate(void* value ,
00442                           int typeId,
00443                           TypeContainer * ipTc,
00444                           XmlPullParser * xpp)
00445 {
00446   
00447   int basetype = sParser_->getBasicContentType(typeId);
00448   
00449   const XSDType * pType = sParser_->getType(typeId);
00450   if (pType && !pType->isSimple()){
00451     
00452     return 0;
00453   }
00454   const SimpleType  *st = static_cast<const SimpleType*>(pType);
00455   
00456   //check for the validity of the value
00457   //if available also check against restrictions in the schema
00458 
00459   if (!ipTc)
00460     ipTc = new TypeContainer(typeId, sParser_);
00461 
00462   if (st && (st->isList() || st->isUnion())){
00463             
00464     std::string val = *((std::string*)value);
00465     ipTc->setValue(val,validateListOrUnion(st,val,xpp));
00466     return ipTc;
00467   }
00468   switch (basetype)
00469     {
00470     case Schema::XSD_INTEGER:
00471     case Schema::XSD_INT:
00472       {
00473         int x= *((int*)value);
00474         if (!st) {
00475           ipTc->setValue(x);
00476         }
00477         else{
00478 
00479           ipTc->setValue(x,st->isValidInt(x));
00480         }
00481         break;
00482       }
00483     case Schema::XSD_BYTE:
00484       {
00485         char c= *((char*)value);
00486         ipTc->setValue(c);
00487       }
00488       break;
00489     case Schema::XSD_FLOAT:
00490       {
00491         float f = *((float*)value);
00492         if (!st) {
00493           
00494           ipTc->setValue(f);
00495           
00496         }else{
00497           
00498           ipTc->setValue(f,st->isValidFloat(f));
00499         }
00500         break;
00501       }
00502     case Schema::XSD_DOUBLE:
00503     case Schema::XSD_DECIMAL:
00504       {
00505         double db = *((double*)value);
00506         ipTc->setValue(db);
00507       }
00508       break;
00509     case Schema::XSD_LONG:
00510       {
00511         long l = *((long*)value);
00512         ipTc->setValue(l);
00513       }
00514       break;
00515     case Schema::XSD_POSINT:
00516     case Schema::XSD_ULONG:
00517       {
00518         unsigned long  ul= *((unsigned  long*)value);
00519         ipTc->setValue(ul);
00520       }
00521       break;
00522     case Schema::XSD_BOOLEAN:
00523       {
00524         bool b  = *((bool*)value);
00525         ipTc->setValue(b);
00526         break;
00527       }
00528     case Schema::XSD_QNAME:
00529       {
00530         Qname q  = *((Qname* )value);
00531         ipTc->setValue(q);
00532       }
00533       break;
00534     case Schema::XSD_STRING:
00535     default: 
00536       {
00537         std::string val = *((std::string* )value);
00538         if (!st) {
00539           
00540           ipTc->setValue(val);
00541         }
00542         else{
00543           
00544           ipTc->setValue(val,st->isValidString(val));
00545         }
00546       }
00547       break;
00548     }
00549 
00550   return  ipTc;
00551 }
00552 
00553 /*
00554  *  This method validates all supported simple types
00555  *  Both native atomic types and schema defined 
00556  */
00557 
00558 TypeContainer *
00559 SchemaValidator::validate(const string & val,
00560                           int typeId,
00561                           TypeContainer *ipTc,
00562                           XmlPullParser * xpp)
00563 {
00564 
00565   int basetype = sParser_->getBasicContentType(typeId);
00566   if (basetype == Schema::XSD_INVALID) {
00567     
00568     return 0;
00569   }
00570   
00571   const XSDType * pType = sParser_->getType(typeId);
00572   if (pType && 
00573       !pType->isSimple() && 
00574       pType->getContentModel() != Schema::Simple){
00575     
00576     return 0;
00577   }
00578 
00579   if (pType && !pType->isSimple() && 
00580       pType->getContentModel() ==Schema::Simple) {
00581     //this is a complex type but has a simple content model
00582     
00583     const ComplexType * ct = static_cast<const ComplexType*>(pType);
00584     int contentType = ct->getContentType();
00585     return validate(val,contentType,ipTc,xpp);
00586 
00587   }
00588   const SimpleType  *st = static_cast<const SimpleType*>(pType);
00589   
00590   //check for the validity of the value
00591   //if available also check against restrictions in the schema
00592 
00593   if (!ipTc)
00594     ipTc = new TypeContainer(typeId, sParser_);
00595   ipTc->setValAsString(val);
00596 
00597   while(ipTc->isValueValid()){
00598     
00599     extractSimpleType(val, basetype, ipTc, st, xpp);
00600 
00601     
00602     if(!st || (st && (st->isList() || st->isUnion()))){
00603       
00604       break;
00605       //if we validated an atomic type we are done
00606       //if we just validated a list or union,there is no need 
00607       //to continue checking base types
00608     }
00609 
00610     if (!sParser_->isBasicType(st->getBaseTypeId())){
00611       
00612       st=static_cast<const SimpleType*>(sParser_->getType(st->getBaseTypeId()));
00613     }
00614     else{
00615       st = 0;
00616     }
00617   }
00618   return ipTc;
00619 }
00620 
00621 
00622 void 
00623 SchemaValidator::extractSimpleType(const std::string & val,
00624                                    int basetype,
00625                                    TypeContainer * ipTc,
00626                                    const SimpleType * st,
00627                                    XmlPullParser * xpp)
00628 {
00629 
00630   if (st && (st->isList() || st->isUnion())){
00631             
00632     ipTc->setValue(val,validateListOrUnion(st,val,xpp));
00633     return;
00634   }
00635   
00636   istringstream istr(val);
00637   int x;
00638   double db;
00639   long l;
00640   char c;
00641   unsigned long  ul;
00642   float f;
00643 
00644   switch (basetype)
00645     {
00646     case Schema::XSD_INTEGER:
00647     case Schema::XSD_INT:
00648       {
00649         istr >> x;
00650         if (!st) {
00651           ipTc->setValue(x,!istr.fail());
00652         }
00653         else{
00654 
00655           ipTc->setValue(x,!istr.fail() && st->isValidInt(x));
00656         }
00657         break;
00658       }
00659     case Schema::XSD_BYTE:
00660       istr >> c;
00661       ipTc->setValue(c,!istr.fail());
00662       break;
00663     case Schema::XSD_FLOAT:
00664       {
00665         istr >> f;
00666         if (!st) {
00667           ipTc->setValue(f,!istr.fail());
00668         }else{
00669           ipTc->setValue(f,!istr.fail() && st->isValidFloat(f));
00670         }
00671         break;
00672       }
00673     case Schema::XSD_DOUBLE:
00674     case Schema::XSD_DECIMAL:
00675       istr >> db;
00676       ipTc->setValue(db,!istr.fail());
00677       break;
00678     case Schema::XSD_LONG:
00679       istr >> l;
00680       ipTc->setValue(l,!istr.fail());
00681       break;
00682     case Schema::XSD_POSINT:
00683     case Schema::XSD_ULONG:
00684       istr >> ul;
00685       ipTc->setValue(ul,!istr.fail());
00686       break;
00687     case Schema::XSD_BOOLEAN:
00688       {
00689 
00690         if(val=="true" ||
00691            val=="yes" ||
00692            val=="1")
00693         
00694           ipTc->setValue(true);
00695         else
00696           ipTc->setValue(false);
00697         break;
00698       }
00699     case Schema::XSD_QNAME:
00700       {
00701         Qname q(val);
00702         if (xpp)
00703           q.setNamespace(xpp->getNamespace(q.getPrefix()));
00704         ipTc->setValue(q);
00705         break;
00706       }
00707     case Schema::XSD_STRING:
00708     default: 
00709       {
00710         if (!st) {
00711             
00712           ipTc->setValue(val);
00713         }
00714         else{
00715           if (basetype == Schema::XSD_STRING)
00716             ipTc->setValue(val,st->isValidString(val));
00717           else
00718             ipTc->setValue(val);//other types such as date for which no validation is done
00719         }
00720       }
00721       break;
00722     }
00723 }
00724 
00725 /*
00726  * This function validates a string as a list or union 
00727  * for the simple type 
00728  */
00729 
00730 bool
00731 SchemaValidator::validateListOrUnion(const SimpleType* st,
00732                                      const std::string &val,
00733                                      XmlPullParser * xpp)
00734 {
00735   if (st->isList()){
00736    
00737     size_t s = 0;
00738 
00739     while(s < val.length()){
00740       while(val[s]==' ')s++;
00741       std::string t = val.substr(s,val.find(' ',s)-s);
00742       TypeContainer * tc = validate(t,st->getBaseTypeId(),0,xpp);
00743       if (!(tc && tc->isValueValid()))
00744         return false;
00745       s+=t.length()+1;
00746     }
00747     return true ;
00748   
00749   }else if (st->isUnion()){
00750     
00751     std::list<int>::const_iterator it= st->unionTypes()->begin();
00752     while (it!=st->unionTypes()->end()){
00753       TypeContainer * tc = validate(val,*it,0,xpp);
00754       if (tc && tc->isValueValid())
00755         return true;
00756     }
00757     return false;
00758   }
00759   else{
00760     return false;
00761   }
00762 }
00763 /*
00764  * This function searches for a child element in a complex type 
00765  * The iterator pElem is set to point to the found element
00766  * rewind controls whether a search is to be done by resetting pElem 
00767  * to the begining of the list 
00768  * Returns true if element is found else false 
00769  */
00770 
00771 bool
00772 SchemaValidator::findElement(ContentModel::ContentsIterator start, 
00773                              ContentModel::ContentsIterator end, 
00774                              std::string name,
00775                              ContentModel::ContentsIterator & found)
00776 {
00777   for (ContentModel::ContentsIterator ci=start;
00778        ci!=end;
00779        ci++){
00780     
00781     if(ci->second==ContentModel::Particle){
00782 #ifdef LOGGING   
00783        std::cout<<"Looking for "<<ci->first.e->getName()<<" in   "<<name<<std::endl;
00784 #endif
00785       if(ci->first.e->getName()==name ||
00786          ci->first.e->getName() == "*")//* is  a hack for soap arrays
00787         {
00788           found=ci;
00789           return true;
00790         }
00791     }
00792   }
00793   return false;
00794 }
00795 
00796 void SchemaValidator::error(const std::string& mesg,XmlPullParser* xpp)
00797 {
00798     
00799   SchemaParserException spe(mesg + "\nError validating schema instance\n");
00800   if(xpp){
00801     
00802     spe.line=xpp->getLineNumber();
00803     spe.col=xpp->getColumnNumber();
00804   }
00805   throw spe;
00806 }
00807 
00808 
00809 bool
00810 SchemaValidator::checkAttributeOccurence(const ComplexType* ct ,
00811                                          XmlPullParser* xpp)
00812 {
00813 
00814   if (ct->getNumAttributes() > 0)
00815     {
00816       for (int i = 0; i < ct->getNumAttributes(); i++)
00817         {
00818           const Attribute*at = ct->getAttribute(i);
00819               
00820           /*
00821             Check for the correctness of each attribute
00822           */
00823           string attVal = xpp->getAttributeValue("", at->getName());
00824           if (attVal.empty())
00825             {
00826               if (at->isRequired())
00827                 error("Required attribute \"" + at->getName() +
00828                       "\" missing or empty",xpp);
00829 
00830               else
00831                 continue;
00832             }
00833         }
00834     }
00835   return true;
00836 }
00837 
00838 
00839 
00840 bool
00841 SchemaValidator::instance(const std::string& tag,
00842                           Schema::Type type_id)
00843 
00844 {
00845 
00846   //generate an instance of the given type
00847   std::string nsp = sParser_->getNamespace();
00848   xmlStream_ = new XmlSerializer(ostr_); //xml serializer
00849   
00850   if (!nsp.empty()) 
00851     xmlStream_->setPrefix("s",nsp);
00852   
00853   xmlStream_->setPrefix("xsi",Schema::SchemaInstaceUri);
00854   xmlStream_->startDocument("UTF-8",false);
00855 
00856   return instance1(tag,type_id);
00857 }
00858 
00859 bool
00860 SchemaValidator::instance1(const std::string &tag,
00861                            Schema::Type type_id)
00862 {
00863 
00864   std::string nsp = sParser_->getNamespace();
00865   static bool first = false;
00866   xmlStream_->startTag(nsp,tag);
00867   if (!first){
00868     xmlStream_->attribute("",
00869                           "xmlns",
00870                           nsp);
00871     first = true;
00872   }
00873 
00874 
00875   //  xmlStream_->attribute(Schema::SchemaInstaceUri,
00876   //            "type",
00877   //            "s:"+sParser_->getTypeName(type_id));
00878   const XSDType * pType = sParser_->getType(type_id);
00879 
00880   if ( pType== 0 ||
00881        pType->isSimple()){
00882 
00883     xmlStream_->text(""); //simple content types
00884     
00885   }
00886   else {
00887 
00888     const ComplexType * ct =
00889       static_cast<const ComplexType*>(pType);
00890     
00891     //print attributes if any
00892     if (ct->getNumAttributes() > 0) {
00893       
00894       for (int i = 0; i < ct->getNumAttributes(); i++) {
00895         
00896         const Attribute*at = ct->getAttribute(i);
00897         xmlStream_->attribute(sParser_->getNamespace(),at->getName(),"");
00898       }
00899     }
00900   
00901 
00902     if (ct->getContentModel() == Schema::Simple) {
00903       
00904       xmlStream_->text("");
00905     }
00906     else{
00907 
00908       ContentModel* cm=ct->getContents();
00909       instanceCM(cm);
00910       
00911     }
00912   }
00913   xmlStream_->endTag(nsp,tag);
00914   return  true;
00915 }
00916 
00917 
00918 
00919 
00920 void
00921 SchemaValidator::instanceCM(ContentModel *cm)
00922         
00923 {
00924   
00925   ContentModel::ContentsIterator cit_b=cm->begin();
00926   ContentModel::ContentsIterator cit_e=cm->end();
00927   ContentModel::ContentsIterator ci=cit_b;
00928 
00929   switch (cm->getCompositor())
00930     {
00931     case Schema::All:
00932     case Schema::Sequence:
00933     case Schema::Choice:
00934       {
00935         // a simple logic to start with
00936         // not taking care of all,choice ,sequence as of now
00937         
00938         for (ci=cit_b;ci!=cit_e;ci++){
00939           
00940           if(ci->second==ContentModel::Particle &&
00941              ci->first.e->getMax() > 0){
00942 
00943             const SchemaParser* s1Parser = sParser_;
00944             Schema::Type t=(Schema::Type)ci->first.e->getType();
00945             
00946             if (!ci->first.e->getTypeNamespace().empty() &&
00947                 sParser_->isImported(ci->first.e->getTypeNamespace()) &&
00948                 sParser_->getNamespace() != ci->first.e->getTypeNamespace()) {
00949         
00950               //here the type of the element is defined in another imported schemaparser
00951               //so try to get the pointer.
00952               t = (Schema::Type)sParser_->getType(t)->getTypeId();
00953               sParser_ = sParser_->getImportedSchemaParser(ci->first.e->getTypeNamespace());
00954             }
00955            
00956             instance1(ci->first.e->getName(),t);
00957             sParser_ = s1Parser;
00958           }
00959           else if (ci->second==ContentModel::Container) {
00960             
00961             //nested xsd:sequence inside choice..nested content models
00962             instanceCM(ci->first.c);
00963               
00964           }
00965           else if (ci->second==ContentModel::ParticleGroup){
00966             
00967             //xsd:group inside 
00968             instanceCM(ci->first.g->getContents());
00969                                 
00970           }
00971         }
00972         break;
00973       }
00974     }
00975 }
00976 
00977 }
00978 //TODO validation of <any>
00979 //TODO validation of base64binary,hexBinary
00980 //TODO validation of types derived by extension/restriction of complex types

Generated on Sat May 3 16:28:59 2008 for wsdlpull by  doxygen 1.4.6