GME  13
ListDatatypeValidator.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  * 
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  * 
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: ListDatatypeValidator.cpp 695949 2008-09-16 15:57:44Z borisk $
00020  */
00021 
00022 // ---------------------------------------------------------------------------
00023 //  Includes
00024 // ---------------------------------------------------------------------------
00025 #include <xercesc/validators/datatype/ListDatatypeValidator.hpp>
00026 #include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp>
00027 #include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp>
00028 #include <xercesc/util/OutOfMemoryException.hpp>
00029 
00030 XERCES_CPP_NAMESPACE_BEGIN
00031 
00032 static const int BUF_LEN = 64;
00033 
00034 // ---------------------------------------------------------------------------
00035 //  Constructors and Destructor
00036 // ---------------------------------------------------------------------------
00037 ListDatatypeValidator::ListDatatypeValidator(MemoryManager* const manager)
00038 :AbstractStringValidator(0, 0, 0, DatatypeValidator::List, manager)
00039 ,fContent(0)
00040 {}
00041 
00042 ListDatatypeValidator::ListDatatypeValidator(
00043                           DatatypeValidator*            const baseValidator
00044                         , RefHashTableOf<KVStringPair>* const facets
00045                         , RefArrayVectorOf<XMLCh>*           const enums
00046                         , const int                           finalSet
00047                         , MemoryManager* const manager)
00048 :AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::List, manager)
00049 ,fContent(0)
00050 {
00051     //
00052     // baseValidator shall either
00053     // an atomic DTV which servers as itemType, or
00054     // another ListDTV from which, this ListDTV is derived by restriction.
00055     //
00056     // In either case, it shall be not null
00057     //
00058     if (!baseValidator)
00059         ThrowXMLwithMemMgr(InvalidDatatypeFacetException, XMLExcepts::FACET_List_Null_baseValidator, manager);
00060 
00061     init(enums, manager);
00062 }
00063 
00064 ListDatatypeValidator::~ListDatatypeValidator()
00065 {}
00066 
00067 DatatypeValidator* ListDatatypeValidator::newInstance
00068 (
00069       RefHashTableOf<KVStringPair>* const facets
00070     , RefArrayVectorOf<XMLCh>* const      enums
00071     , const int                           finalSet
00072     , MemoryManager* const                manager
00073 )
00074 {
00075     return (DatatypeValidator*) new (manager) ListDatatypeValidator(this, facets, enums, finalSet, manager);
00076 }
00077 
00078 
00079 int ListDatatypeValidator::compare(const XMLCh*     const lValue
00080                                  , const XMLCh*     const rValue
00081                                  , MemoryManager*   const manager)
00082 {
00083     DatatypeValidator* theItemTypeDTV = getItemTypeDTV();
00084     BaseRefVectorOf<XMLCh>* lVector = XMLString::tokenizeString(lValue, manager);
00085     Janitor<BaseRefVectorOf<XMLCh> > janl(lVector);
00086     BaseRefVectorOf<XMLCh>* rVector = XMLString::tokenizeString(rValue, manager);
00087     Janitor<BaseRefVectorOf<XMLCh> > janr(rVector);
00088 
00089     XMLSize_t lNumberOfTokens = lVector->size();
00090     XMLSize_t rNumberOfTokens = rVector->size();
00091 
00092     if (lNumberOfTokens < rNumberOfTokens)
00093         return -1;
00094     else if (lNumberOfTokens > rNumberOfTokens)
00095         return 1;
00096     else
00097     { //compare each token
00098         for ( XMLSize_t i = 0; i < lNumberOfTokens; i++)
00099         {
00100             int returnValue = theItemTypeDTV->compare(lVector->elementAt(i), rVector->elementAt(i), manager);
00101             if (returnValue != 0)
00102                 return returnValue; //REVISIT: does it make sense to return -1 or +1..?
00103         }
00104         return 0;
00105     }
00106 
00107 }
00108 
00109 void ListDatatypeValidator::validate( const XMLCh*             const content
00110                                     ,       ValidationContext* const context
00111                                     ,       MemoryManager*     const manager)
00112 {
00113     setContent(content);
00114     BaseRefVectorOf<XMLCh>* tokenVector = XMLString::tokenizeString(content, manager);
00115     Janitor<BaseRefVectorOf<XMLCh> > janName(tokenVector);
00116     checkContent(tokenVector, content, context, false, manager);
00117 }
00118 
00119 void ListDatatypeValidator::checkContent( const XMLCh*             const content
00120                                          ,      ValidationContext* const context
00121                                          ,      bool                     asBase
00122                                          ,      MemoryManager*     const manager)
00123 {
00124     setContent(content);
00125     BaseRefVectorOf<XMLCh>* tokenVector = XMLString::tokenizeString(content, manager);
00126     Janitor<BaseRefVectorOf<XMLCh> > janName(tokenVector);
00127     checkContent(tokenVector, content, context, asBase, manager);
00128 }
00129 
00130 //
00131 // here content is a list of items
00132 //
00133 void ListDatatypeValidator::checkContent(       BaseRefVectorOf<XMLCh>*       tokenVector
00134                                         , const XMLCh*                  const content
00135                                         ,       ValidationContext*      const context
00136                                         ,       bool                          asBase
00137                                         ,       MemoryManager*          const manager)
00138 {
00139     DatatypeValidator* bv = getBaseValidator();
00140 
00141     if (bv->getType() == DatatypeValidator::List)
00142         ((ListDatatypeValidator*)bv)->checkContent(tokenVector, content, context, true, manager);
00143     else
00144     {   // the ultimate itemType DTV
00145         for (unsigned int i = 0; i < tokenVector->size(); i++)
00146             bv->validate(tokenVector->elementAt(i), context, manager);
00147     }
00148 
00149     int thisFacetsDefined = getFacetsDefined();
00150 
00151     // we check pattern first
00152     if ( (thisFacetsDefined & DatatypeValidator::FACET_PATTERN ) != 0 )
00153     {
00154         //check every item in the list as a whole
00155         if (getRegex()->matches(content, manager) == false)
00156         {
00157             ThrowXMLwithMemMgr2(InvalidDatatypeValueException
00158                     , XMLExcepts::VALUE_NotMatch_Pattern
00159                     , content
00160                     , getPattern()
00161                     , manager);
00162         }
00163 
00164     }
00165 
00166     // if this is a base validator, we only need to check pattern facet
00167     // all other facet were inherited by the derived type
00168     if (asBase)
00169         return;
00170 
00171     XMLSize_t tokenNumber = tokenVector->size();
00172 
00173     if (((thisFacetsDefined & DatatypeValidator::FACET_MAXLENGTH) != 0) &&
00174         (tokenNumber > getMaxLength()))
00175     {
00176         XMLCh value1[BUF_LEN+1];
00177         XMLCh value2[BUF_LEN+1];
00178         XMLString::sizeToText(tokenNumber, value1, BUF_LEN, 10, manager);
00179         XMLString::sizeToText(getMaxLength(), value2, BUF_LEN, 10, manager);
00180 
00181         ThrowXMLwithMemMgr3(InvalidDatatypeValueException
00182                 , XMLExcepts::VALUE_GT_maxLen
00183                 , getContent()
00184                 , value1
00185                 , value2
00186                 , manager);
00187     }
00188 
00189     if (((thisFacetsDefined & DatatypeValidator::FACET_MINLENGTH) != 0) &&
00190         (tokenNumber < getMinLength()))
00191     {
00192         XMLCh value1[BUF_LEN+1];
00193         XMLCh value2[BUF_LEN+1];
00194         XMLString::sizeToText(tokenNumber, value1, BUF_LEN, 10, manager);
00195         XMLString::sizeToText(getMinLength(), value2, BUF_LEN, 10, manager);
00196 
00197         ThrowXMLwithMemMgr3(InvalidDatatypeValueException
00198                 , XMLExcepts::VALUE_LT_minLen
00199                 , getContent()
00200                 , value1
00201                 , value2
00202                 , manager);
00203     }
00204 
00205     if (((thisFacetsDefined & DatatypeValidator::FACET_LENGTH) != 0) &&
00206         (tokenNumber != AbstractStringValidator::getLength()))
00207     {
00208         XMLCh value1[BUF_LEN+1];
00209         XMLCh value2[BUF_LEN+1];
00210         XMLString::sizeToText(tokenNumber, value1, BUF_LEN, 10, manager);
00211         XMLString::sizeToText(AbstractStringValidator::getLength(), value2, BUF_LEN, 10, manager);
00212 
00213         ThrowXMLwithMemMgr3(InvalidDatatypeValueException
00214                 , XMLExcepts::VALUE_NE_Len
00215                 , getContent()
00216                 , value1
00217                 , value2
00218                 , manager);
00219     }
00220 
00221     if ((thisFacetsDefined & DatatypeValidator::FACET_ENUMERATION) != 0 &&
00222         (getEnumeration() != 0))
00223     {
00224         XMLSize_t i;
00225         XMLSize_t enumLength = getEnumeration()->size();
00226 
00227         for ( i = 0; i < enumLength; i++)
00228         {
00229             //optimization: we do a lexical comparision first
00230             // this may be faster for string and its derived
00231             if (XMLString::equals(getEnumeration()->elementAt(i), getContent()))
00232                 break; // a match found
00233 
00234             // do a value space check
00235             // this is needed for decimal (and probably other types
00236             // such as datetime related)
00237             // eg.
00238             // tokenVector = "1 2 3.0 4" vs enumeration = "1 2 3 4.0"
00239             //
00240             if (valueSpaceCheck(tokenVector, getEnumeration()->elementAt(i), manager))
00241                 break;
00242         }
00243 
00244         if (i == enumLength)
00245             ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, getContent(), manager);
00246 
00247     } // enumeration
00248 
00249 }
00250 
00251 bool ListDatatypeValidator::valueSpaceCheck(BaseRefVectorOf<XMLCh>* tokenVector
00252                                           , const XMLCh*    const  enumStr
00253                                           , MemoryManager*  const  manager) const
00254 {
00255     DatatypeValidator* theItemTypeDTV = getItemTypeDTV();
00256     BaseRefVectorOf<XMLCh>* enumVector = XMLString::tokenizeString(enumStr, manager);
00257     Janitor<BaseRefVectorOf<XMLCh> > janName(enumVector);
00258 
00259     if (tokenVector->size() != enumVector->size())
00260         return false;
00261 
00262     for ( unsigned int j = 0; j < tokenVector->size(); j++ )
00263     {
00264         if (theItemTypeDTV->compare(tokenVector->elementAt(j), enumVector->elementAt(j), manager) != 0)
00265             return false;
00266     }
00267 
00268     return true;
00269 }
00270 
00271 DatatypeValidator* ListDatatypeValidator::getItemTypeDTV() const
00272 {
00273     DatatypeValidator* bdv = this->getBaseValidator();
00274 
00275     while (bdv->getType() == DatatypeValidator::List)
00276         bdv = bdv->getBaseValidator();
00277 
00278     return bdv;
00279 }
00280 
00281 // ---------------------------------------------------------------------------
00282 //  Utilities
00283 // ---------------------------------------------------------------------------
00284 
00285 void ListDatatypeValidator::checkValueSpace(const XMLCh* const
00286                                             , MemoryManager* const)
00287 {}
00288 
00289 XMLSize_t ListDatatypeValidator::getLength(const XMLCh* const content
00290                                      , MemoryManager* const manager) const
00291 {
00292     BaseRefVectorOf<XMLCh>* tokenVector = XMLString::tokenizeString(content, manager);
00293     Janitor<BaseRefVectorOf<XMLCh> > janName(tokenVector);
00294 
00295     return tokenVector->size();
00296 }
00297 
00298 void ListDatatypeValidator::inspectFacetBase(MemoryManager* const manager)
00299 {
00300 
00301     //
00302     // we are pretty sure baseValidator is not null
00303     //
00304 
00305     if (getBaseValidator()->getType() == DatatypeValidator::List)
00306     {
00307         AbstractStringValidator::inspectFacetBase(manager);
00308     }
00309     else
00310     {
00311         // the first level ListDTV
00312         // check 4.3.5.c0 must: enumeration values from the value space of base
00313         if ( ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0) &&
00314              (getEnumeration() !=0)                                              )
00315         {
00316             XMLSize_t i;
00317             XMLSize_t enumLength = getEnumeration()->size();
00318             try
00319             {
00320                 for ( i = 0; i < enumLength; i++)
00321                 {
00322                     // ask the itemType for a complete check
00323                     BaseRefVectorOf<XMLCh>* tempList = XMLString::tokenizeString(getEnumeration()->elementAt(i), manager);
00324                     Janitor<BaseRefVectorOf<XMLCh> >    jan(tempList);
00325                     XMLSize_t tokenNumber = tempList->size();
00326 
00327                     try
00328                     {
00329                         for ( XMLSize_t j = 0; j < tokenNumber; j++)
00330                             getBaseValidator()->validate(tempList->elementAt(j), (ValidationContext*)0, manager);
00331                     }
00332                     catch(const OutOfMemoryException&)
00333                     {
00334                         jan.release();
00335 
00336                         throw;
00337                     }
00338 #if 0
00339 // spec says that only base has to checkContent                    
00340                     // enum shall pass this->checkContent() as well.
00341                     checkContent(getEnumeration()->elementAt(i), (ValidationContext*)0, false, manager);
00342 #endif
00343                 }
00344             }
00345 
00346             catch ( XMLException& )
00347             {
00348                 ThrowXMLwithMemMgr1(InvalidDatatypeFacetException
00349                         , XMLExcepts::FACET_enum_base
00350                         , getEnumeration()->elementAt(i)
00351                         , manager);
00352             }
00353 
00354         }
00355 
00356     }
00357 
00358 }// End of inspectFacetBase()
00359 
00360 void ListDatatypeValidator::inheritFacet()
00361 {
00362 
00363     //iff the base validator is List, then we inherit
00364     //
00365     if (getBaseValidator()->getType() == DatatypeValidator::List)
00366     {
00367         AbstractStringValidator::inheritFacet();
00368     }
00369 
00370 }
00371 
00372 /***
00373  * 2.5.1.2 List datatypes   
00374  *   
00375  * The canonical-lexical-representation for the list datatype is defined as 
00376  * the lexical form in which each item in the list has the canonical 
00377  * lexical representation of its itemType.
00378  ***/
00379 const XMLCh* ListDatatypeValidator::getCanonicalRepresentation(const XMLCh*         const rawData
00380                                                              ,       MemoryManager* const memMgr
00381                                                              ,       bool                 toValidate) const
00382 {
00383     MemoryManager* toUse = memMgr? memMgr : getMemoryManager();
00384     ListDatatypeValidator* temp = (ListDatatypeValidator*) this;
00385     temp->setContent(rawData);
00386     BaseRefVectorOf<XMLCh>* tokenVector = XMLString::tokenizeString(rawData, toUse);
00387     Janitor<BaseRefVectorOf<XMLCh> > janName(tokenVector);    
00388 
00389     if (toValidate)
00390     {
00391         try
00392         {
00393             temp->checkContent(tokenVector, rawData, 0, false, toUse);
00394         }
00395         catch (...)
00396         {
00397             return 0;
00398         }
00399     }
00400    
00401     XMLSize_t retBufSize = 2 * XMLString::stringLen(rawData);
00402     XMLCh* retBuf = (XMLCh*) toUse->allocate(retBufSize * sizeof(XMLCh));
00403     retBuf[0] = 0;
00404     XMLCh* retBufPtr = retBuf;
00405     DatatypeValidator* itemDv = this->getItemTypeDTV();
00406 
00407     try 
00408     {
00409         for (unsigned int i = 0; i < tokenVector->size(); i++)
00410         {
00411             XMLCh* itemCanRep = (XMLCh*) itemDv->getCanonicalRepresentation(tokenVector->elementAt(i), toUse, false);
00412             XMLSize_t itemLen = XMLString::stringLen(itemCanRep); 
00413 
00414             if(retBufPtr+itemLen+2 >= retBuf+retBufSize)
00415             {
00416                 // need to resize
00417                 XMLCh * oldBuf = retBuf;
00418                 retBuf = (XMLCh*) toUse->allocate(retBufSize * sizeof(XMLCh) * 4);
00419                 memcpy(retBuf, oldBuf, retBufSize * sizeof(XMLCh ));
00420                 retBufPtr = (retBufPtr - oldBuf) + retBuf;
00421                 toUse->deallocate(oldBuf);
00422                 retBufSize <<= 2;
00423             }
00424 
00425             XMLString::catString(retBufPtr, itemCanRep);
00426             retBufPtr = retBufPtr + itemLen;
00427             *(retBufPtr++) = chSpace;
00428             *(retBufPtr) = chNull;
00429             toUse->deallocate(itemCanRep);
00430         }
00431 
00432         return retBuf;
00433 
00434     }
00435     catch (...)
00436     {
00437         return 0;
00438     }
00439 }
00440 
00441 /***
00442  * Support for Serialization/De-serialization
00443  ***/
00444 
00445 IMPL_XSERIALIZABLE_TOCREATE(ListDatatypeValidator)
00446 
00447 void ListDatatypeValidator::serialize(XSerializeEngine& serEng)
00448 {
00449     AbstractStringValidator::serialize(serEng);
00450 
00451     //don't serialize fContent, since it is NOT owned and 
00452     //will be reset each time validate()/checkContent() invoked.
00453 }
00454 
00455 XERCES_CPP_NAMESPACE_END
00456