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: UnionDatatypeValidator.cpp 677559 2008-07-17 11:35:27Z amassari $ 00020 */ 00021 00022 // --------------------------------------------------------------------------- 00023 // Includes 00024 // --------------------------------------------------------------------------- 00025 #include <xercesc/validators/datatype/UnionDatatypeValidator.hpp> 00026 #include <xercesc/validators/datatype/InvalidDatatypeFacetException.hpp> 00027 #include <xercesc/validators/datatype/InvalidDatatypeValueException.hpp> 00028 #include <xercesc/util/OutOfMemoryException.hpp> 00029 00030 #include <xercesc/internal/XTemplateSerializer.hpp> 00031 00032 XERCES_CPP_NAMESPACE_BEGIN 00033 00034 static const unsigned int BUF_LEN = 64; 00035 00036 // --------------------------------------------------------------------------- 00037 // Constructors and Destructor 00038 // --------------------------------------------------------------------------- 00039 UnionDatatypeValidator::UnionDatatypeValidator(MemoryManager* const manager) 00040 :DatatypeValidator(0, 0, 0, DatatypeValidator::Union, manager) 00041 ,fEnumerationInherited(false) 00042 ,fMemberTypesInherited(false) 00043 ,fEnumeration(0) 00044 ,fMemberTypeValidators(0) 00045 00046 {} 00047 00048 UnionDatatypeValidator::~UnionDatatypeValidator() 00049 { 00050 cleanUp(); 00051 } 00052 00053 UnionDatatypeValidator::UnionDatatypeValidator( 00054 RefVectorOf<DatatypeValidator>* const memberTypeValidators 00055 , const int finalSet 00056 , MemoryManager* const manager) 00057 :DatatypeValidator(0, 0, finalSet, DatatypeValidator::Union, manager) 00058 ,fEnumerationInherited(false) 00059 ,fMemberTypesInherited(false) 00060 ,fEnumeration(0) 00061 ,fMemberTypeValidators(0) 00062 { 00063 if ( !memberTypeValidators ) 00064 { 00065 ThrowXMLwithMemMgr(InvalidDatatypeFacetException 00066 , XMLExcepts::FACET_Union_Null_memberTypeValidators, manager); 00067 } 00068 00069 // no pattern, no enumeration 00070 fMemberTypeValidators = memberTypeValidators; 00071 } 00072 00073 typedef JanitorMemFunCall<UnionDatatypeValidator> CleanupType; 00074 00075 UnionDatatypeValidator::UnionDatatypeValidator( 00076 DatatypeValidator* const baseValidator 00077 , RefHashTableOf<KVStringPair>* const facets 00078 , RefArrayVectorOf<XMLCh>* const enums 00079 , const int finalSet 00080 , MemoryManager* const manager 00081 , RefVectorOf<DatatypeValidator>* const memberTypeValidators 00082 , const bool memberTypesInherited 00083 ) 00084 :DatatypeValidator(baseValidator, facets, finalSet, DatatypeValidator::Union, manager) 00085 ,fEnumerationInherited(false) 00086 ,fMemberTypesInherited(memberTypesInherited) 00087 ,fEnumeration(0) 00088 ,fMemberTypeValidators(memberTypeValidators) 00089 { 00090 // 00091 // baseValidator another UnionDTV from which, 00092 // this UnionDTV is derived by restriction. 00093 // it shall be not null 00094 // 00095 if (!baseValidator) 00096 { 00097 ThrowXMLwithMemMgr(InvalidDatatypeFacetException 00098 , XMLExcepts::FACET_Union_Null_baseValidator, manager); 00099 } 00100 00101 if (baseValidator->getType() != DatatypeValidator::Union) 00102 { 00103 XMLCh value1[BUF_LEN+1]; 00104 XMLString::binToText(baseValidator->getType(), value1, BUF_LEN, 10, manager); 00105 ThrowXMLwithMemMgr1(InvalidDatatypeFacetException 00106 , XMLExcepts::FACET_Union_invalid_baseValidatorType 00107 , value1 00108 , manager); 00109 } 00110 00111 CleanupType cleanup(this, &UnionDatatypeValidator::cleanUp); 00112 00113 try 00114 { 00115 init(baseValidator, facets, enums, manager); 00116 } 00117 catch(const OutOfMemoryException&) 00118 { 00119 // Don't cleanup when out of memory, since executing the 00120 // code can cause problems. 00121 cleanup.release(); 00122 00123 throw; 00124 } 00125 00126 cleanup.release(); 00127 } 00128 00129 void UnionDatatypeValidator::init(DatatypeValidator* const baseValidator 00130 , RefHashTableOf<KVStringPair>* const facets 00131 , RefArrayVectorOf<XMLCh>* const enums 00132 , MemoryManager* const manager) 00133 { 00134 if (enums) 00135 setEnumeration(enums, false); 00136 00137 // Set Facets if any defined 00138 if (facets) 00139 { 00140 XMLCh* key; 00141 XMLCh* value; 00142 RefHashTableOfEnumerator<KVStringPair> e(facets, false, manager); 00143 00144 while (e.hasMoreElements()) 00145 { 00146 KVStringPair pair = e.nextElement(); 00147 key = pair.getKey(); 00148 value = pair.getValue(); 00149 00150 if (XMLString::equals(key, SchemaSymbols::fgELT_PATTERN)) 00151 { 00152 setPattern(value); 00153 if (getPattern()) 00154 setFacetsDefined(DatatypeValidator::FACET_PATTERN); 00155 // do not construct regex until needed 00156 } 00157 else 00158 { 00159 ThrowXMLwithMemMgr1(InvalidDatatypeFacetException 00160 , XMLExcepts::FACET_Invalid_Tag 00161 , key 00162 , manager); 00163 } 00164 }//while 00165 00166 /*** 00167 Schema constraint: Part I -- self checking 00168 ***/ 00169 // Nil 00170 00171 /*** 00172 Schema constraint: Part II base vs derived checking 00173 ***/ 00174 // check 4.3.5.c0 must: enumeration values from the value space of base 00175 if ( ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0) && 00176 (getEnumeration() !=0)) 00177 { 00178 XMLSize_t i = 0; 00179 XMLSize_t enumLength = getEnumeration()->size(); 00180 try 00181 { 00182 for ( ; i < enumLength; i++) 00183 { 00184 // ask parent do a complete check 00185 // 00186 // enum need NOT be passed this->checkContent() 00187 // since there are no other facets for Union, parent 00188 // checking is good enough. 00189 // 00190 baseValidator->validate(getEnumeration()->elementAt(i), (ValidationContext*)0, manager); 00191 00192 } 00193 } 00194 00195 catch ( XMLException& ) 00196 { 00197 ThrowXMLwithMemMgr1(InvalidDatatypeFacetException 00198 , XMLExcepts::FACET_enum_base 00199 , getEnumeration()->elementAt(i) 00200 , manager); 00201 } 00202 } 00203 00204 }// End of Facet setting 00205 00206 /*** 00207 Inherit facets from base.facets 00208 00209 The reason of this inheriting (or copying values) is to ease 00210 schema constraint checking, so that we need NOT trace back to our 00211 very first base validator in the hierachy. Instead, we are pretty 00212 sure checking against immediate base validator is enough. 00213 ***/ 00214 00215 UnionDatatypeValidator *pBaseValidator = (UnionDatatypeValidator*) baseValidator; 00216 00217 // inherit enumeration 00218 if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) !=0) && 00219 ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) == 0)) 00220 { 00221 setEnumeration(pBaseValidator->getEnumeration(), true); 00222 } 00223 00224 } 00225 00226 // 00227 // 1) the bottom level UnionDTV would check against 00228 // pattern and enumeration as well 00229 // 2) each UnionDTV(s) above the bottom level UnionDTV and 00230 // below the native UnionDTV (the top level DTV) 00231 // would check against pattern only. 00232 // 3) the natvie Union DTV (the top level DTV) would invoke 00233 // memberTypeValidator to validate 00234 // 00235 void UnionDatatypeValidator::checkContent(const XMLCh* const content 00236 , ValidationContext* const context 00237 , bool asBase 00238 , MemoryManager* const manager) 00239 { 00240 00241 DatatypeValidator* bv = getBaseValidator(); 00242 if (bv) 00243 ((UnionDatatypeValidator*)bv)->checkContent(content, context, true, manager); 00244 else 00245 { // 3) native union type 00246 // check content against each member type validator in Union 00247 // report an error only in case content is not valid against all member datatypes. 00248 // 00249 bool memTypeValid = false; 00250 for ( unsigned int i = 0; i < fMemberTypeValidators->size(); ++i ) 00251 { 00252 if ( memTypeValid ) 00253 break; 00254 00255 try 00256 { 00257 fMemberTypeValidators->elementAt(i)->validate(content, context, manager); 00258 memTypeValid = true; 00259 00260 //set the validator of the type actually used to validate the content 00261 DatatypeValidator *dtv = fMemberTypeValidators->elementAt(i); 00262 // context will be null during schema construction 00263 if(context) 00264 context->setValidatingMemberType(dtv); 00265 } 00266 catch (XMLException&) 00267 { 00268 //absorbed 00269 } 00270 } // for 00271 00272 if ( !memTypeValid ) 00273 { 00274 ThrowXMLwithMemMgr1(InvalidDatatypeValueException 00275 , XMLExcepts::VALUE_no_match_memberType 00276 , content 00277 , manager); 00278 //( "Content '"+content+"' does not match any union types" ); 00279 } 00280 } 00281 00282 // 1) and 2). we check pattern first 00283 if ( (getFacetsDefined() & DatatypeValidator::FACET_PATTERN ) != 0 ) 00284 { 00285 if (getRegex()->matches(content, manager) == false) 00286 { 00287 ThrowXMLwithMemMgr2(InvalidDatatypeValueException 00288 , XMLExcepts::VALUE_NotMatch_Pattern 00289 , content 00290 , getPattern() 00291 , manager); 00292 } 00293 } 00294 00295 // if this is a base validator, we only need to check pattern facet 00296 // all other facet were inherited by the derived type 00297 if (asBase) 00298 return; 00299 00300 if ((getFacetsDefined() & DatatypeValidator::FACET_ENUMERATION) != 0 && 00301 (getEnumeration() != 0)) 00302 { 00303 00304 // If the content match (compare equal) any enumeration with 00305 // any of the member types, it is considerd valid. 00306 // 00307 RefVectorOf<DatatypeValidator>* memberDTV = getMemberTypeValidators(); 00308 RefArrayVectorOf<XMLCh>* tmpEnum = getEnumeration(); 00309 XMLSize_t memberTypeNumber = memberDTV->size(); 00310 XMLSize_t enumLength = tmpEnum->size(); 00311 00312 for ( XMLSize_t memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex) 00313 { 00314 for ( XMLSize_t enumIndex = 0; enumIndex < enumLength; ++enumIndex) 00315 { 00316 try 00317 { 00318 if (memberDTV->elementAt(memberIndex)->compare(content, tmpEnum->elementAt(enumIndex), manager) == 0) 00319 return; 00320 } 00321 catch (XMLException&) 00322 { 00323 //absorbed 00324 } 00325 } // for enumIndex 00326 } // for memberIndex 00327 00328 ThrowXMLwithMemMgr1(InvalidDatatypeValueException, XMLExcepts::VALUE_NotIn_Enumeration, content, manager); 00329 00330 } // enumeration 00331 00332 } 00333 00334 // 00335 // 00336 // 00337 int UnionDatatypeValidator::compare(const XMLCh* const lValue 00338 , const XMLCh* const rValue 00339 , MemoryManager* const manager) 00340 { 00341 RefVectorOf<DatatypeValidator>* memberDTV = getMemberTypeValidators(); 00342 XMLSize_t memberTypeNumber = memberDTV->size(); 00343 00344 for ( XMLSize_t memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex) 00345 { 00346 // 'compare' can throw exceptions when the datatype is not valid, or just 00347 // return -1; so attempt to validate both values to get the right validator 00348 try 00349 { 00350 memberDTV->elementAt(memberIndex)->validate(lValue, 0, manager); 00351 memberDTV->elementAt(memberIndex)->validate(rValue, 0, manager); 00352 if (memberDTV->elementAt(memberIndex)->compare(lValue, rValue, manager) ==0) 00353 return 0; 00354 } 00355 catch (XMLException&) 00356 { 00357 //absorbed 00358 } 00359 } 00360 00361 //REVISIT: what does it mean for UNION1 to be <less than> or <greater than> UNION2 ? 00362 // As long as -1 or +1 indicates an unequality, return either of them is ok. 00363 return -1; 00364 } 00365 00366 const RefArrayVectorOf<XMLCh>* UnionDatatypeValidator::getEnumString() const 00367 { 00368 return getEnumeration(); 00369 } 00370 00371 /*** 00372 * 2.5.1.3 Union datatypes 00373 * 00374 * The canonical-lexical-representation for a union datatype is defined as the lexical form 00375 * in which the values have the canonical lexical representation of the appropriate memberTypes. 00376 ***/ 00377 const XMLCh* UnionDatatypeValidator::getCanonicalRepresentation(const XMLCh* const rawData 00378 , MemoryManager* const memMgr 00379 , bool toValidate) const 00380 { 00381 MemoryManager* toUse = memMgr? memMgr : getMemoryManager(); 00382 UnionDatatypeValidator* temp = (UnionDatatypeValidator*) this; 00383 00384 if (toValidate) 00385 { 00386 try 00387 { 00388 temp->checkContent(rawData, 0, false, toUse); 00389 } 00390 catch (...) 00391 { 00392 return 0; 00393 } 00394 } 00395 00396 //get the native unionDv 00397 UnionDatatypeValidator* bdv = (UnionDatatypeValidator*) temp->getBaseValidator(); 00398 while (bdv) 00399 { 00400 temp = bdv; 00401 bdv = (UnionDatatypeValidator*) temp->getBaseValidator(); 00402 } 00403 00404 //let the member dv which recognize the rawData, to return 00405 //us the canonical form 00406 for ( unsigned int i = 0; i < temp->fMemberTypeValidators->size(); ++i ) 00407 { 00408 try 00409 { 00410 temp->fMemberTypeValidators->elementAt(i)->validate(rawData, 0, toUse); 00411 return temp->fMemberTypeValidators->elementAt(i)->getCanonicalRepresentation(rawData, toUse, false); 00412 } 00413 catch (XMLException&) 00414 { 00415 //absorbed 00416 } 00417 } 00418 00419 //if no member dv recognize it 00420 return 0; 00421 } 00422 00423 00424 /*** 00425 * Support for Serialization/De-serialization 00426 ***/ 00427 00428 IMPL_XSERIALIZABLE_TOCREATE(UnionDatatypeValidator) 00429 00430 void UnionDatatypeValidator::serialize(XSerializeEngine& serEng) 00431 { 00432 00433 DatatypeValidator::serialize(serEng); 00434 00435 if (serEng.isStoring()) 00436 { 00437 serEng<<fEnumerationInherited; 00438 serEng<<fMemberTypesInherited; 00439 00440 /*** 00441 * Serialize RefArrayVectorOf<XMLCh> 00442 * Serialize RefVectorOf<DatatypeValidator> 00443 ***/ 00444 XTemplateSerializer::storeObject(fEnumeration, serEng); 00445 XTemplateSerializer::storeObject(fMemberTypeValidators, serEng); 00446 } 00447 else 00448 { 00449 serEng>>fEnumerationInherited; 00450 serEng>>fMemberTypesInherited; 00451 00452 /*** 00453 * Deserialize RefArrayVectorOf<XMLCh> 00454 * Deserialize RefVectorOf<DatatypeValidator> 00455 ***/ 00456 XTemplateSerializer::loadObject(&fEnumeration, 8, true, serEng); 00457 XTemplateSerializer::loadObject(&fMemberTypeValidators, 4, false, serEng); 00458 } 00459 } 00460 00461 XERCES_CPP_NAMESPACE_END 00462