GME
13
|
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