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: ValueStore.cpp 804209 2009-08-14 13:15:05Z amassari $ 00020 */ 00021 00022 // --------------------------------------------------------------------------- 00023 // Includes 00024 // --------------------------------------------------------------------------- 00025 #include <xercesc/internal/XMLScanner.hpp> 00026 #include <xercesc/framework/XMLValidator.hpp> 00027 #include <xercesc/validators/datatype/DatatypeValidator.hpp> 00028 #include <xercesc/validators/schema/identity/FieldActivator.hpp> 00029 #include <xercesc/validators/schema/identity/ValueStore.hpp> 00030 #include <xercesc/validators/schema/identity/IC_Field.hpp> 00031 #include <xercesc/validators/schema/identity/IC_KeyRef.hpp> 00032 #include <xercesc/validators/schema/identity/ValueStoreCache.hpp> 00033 00034 XERCES_CPP_NAMESPACE_BEGIN 00035 00036 // 00037 // --------------------------------------------------------------------------- 00038 // ICValueHasher: the hasher for identity constraints values 00039 // --------------------------------------------------------------------------- 00040 XMLSize_t ICValueHasher::getHashVal(const void* key, XMLSize_t mod) const 00041 { 00042 const FieldValueMap* valueMap=(const FieldValueMap*)key; 00043 XMLSize_t hashVal = 0; 00044 00045 XMLSize_t size = valueMap->size(); 00046 for (XMLSize_t j=0; j<size; j++) { 00047 // reach the most generic datatype validator 00048 DatatypeValidator* dv = valueMap->getDatatypeValidatorAt(j); 00049 while(dv && dv->getBaseValidator()) 00050 dv = dv->getBaseValidator(); 00051 const XMLCh* const val = valueMap->getValueAt(j); 00052 const XMLCh* canonVal = (dv && val)?dv->getCanonicalRepresentation(val, fMemoryManager):0; 00053 if(canonVal) 00054 { 00055 hashVal += XMLString::hash(canonVal, mod); 00056 fMemoryManager->deallocate((void*)canonVal); 00057 } 00058 else if(val) 00059 hashVal += XMLString::hash(val, mod); 00060 } 00061 00062 return hashVal % mod; 00063 } 00064 00065 bool ICValueHasher::equals(const void *const key1, const void *const key2) const 00066 { 00067 const FieldValueMap* left=(const FieldValueMap*)key1; 00068 const FieldValueMap* right=(const FieldValueMap*)key2; 00069 00070 XMLSize_t lSize = left->size(); 00071 XMLSize_t rSize = right->size(); 00072 if (lSize == rSize) 00073 { 00074 bool matchFound = true; 00075 00076 for (XMLSize_t j=0; j<rSize; j++) { 00077 if (!isDuplicateOf(left->getDatatypeValidatorAt(j), left->getValueAt(j), 00078 right->getDatatypeValidatorAt(j), right->getValueAt(j))) { 00079 matchFound = false; 00080 break; 00081 } 00082 } 00083 00084 if (matchFound) { // found it 00085 return true; 00086 } 00087 } 00088 return false; 00089 } 00090 00091 bool ICValueHasher::isDuplicateOf(DatatypeValidator* const dv1, const XMLCh* const val1, 00092 DatatypeValidator* const dv2, const XMLCh* const val2) const 00093 { 00094 00095 // if either validator's null, fall back on string comparison 00096 if(!dv1 || !dv2) { 00097 return (XMLString::equals(val1, val2)); 00098 } 00099 00100 bool val1IsEmpty = (val1==0 || *val1==0); 00101 bool val2IsEmpty = (val2==0 || *val2==0); 00102 00103 if (val1IsEmpty && val2IsEmpty) { 00104 00105 if (dv1 == dv2) { 00106 return true; 00107 } 00108 00109 return false; 00110 } 00111 00112 if (val1IsEmpty || val2IsEmpty) { 00113 return false; 00114 } 00115 00116 // find the common ancestor, if there is one 00117 DatatypeValidator* tempVal1 = dv1; 00118 while(tempVal1) 00119 { 00120 DatatypeValidator* tempVal2 = dv2; 00121 for(; tempVal2 != NULL && tempVal2 != tempVal1; tempVal2 = tempVal2->getBaseValidator()) ; 00122 if (tempVal2) 00123 return ((tempVal2->compare(val1, val2, fMemoryManager)) == 0); 00124 tempVal1=tempVal1->getBaseValidator(); 00125 } 00126 00127 // if we're here it means the types weren't related. They are different: 00128 return false; 00129 } 00130 00131 // --------------------------------------------------------------------------- 00132 // ValueStore: Constructors and Destructor 00133 // --------------------------------------------------------------------------- 00134 ValueStore::ValueStore(IdentityConstraint* const ic, 00135 XMLScanner* const scanner, 00136 MemoryManager* const manager) 00137 : fDoReportError(false) 00138 , fValuesCount(0) 00139 , fIdentityConstraint(ic) 00140 , fValues(manager) 00141 , fValueTuples(0) 00142 , fScanner(scanner) 00143 , fMemoryManager(manager) 00144 { 00145 fDoReportError = (scanner && (scanner->getValidationScheme() == XMLScanner::Val_Always)); 00146 } 00147 00148 00149 ValueStore::~ValueStore() 00150 { 00151 delete fValueTuples; 00152 } 00153 00154 // --------------------------------------------------------------------------- 00155 // ValueStore: Helper methods 00156 // --------------------------------------------------------------------------- 00157 void ValueStore::addValue(FieldActivator* const fieldActivator, 00158 IC_Field* const field, 00159 DatatypeValidator* const dv, 00160 const XMLCh* const value) { 00161 00162 if (!fieldActivator->getMayMatch(field) && fDoReportError) { 00163 fScanner->getValidator()->emitError(XMLValid::IC_FieldMultipleMatch); 00164 } 00165 00166 // do we even know this field? 00167 XMLSize_t index; 00168 bool bFound = fValues.indexOf(field, index); 00169 00170 if (!bFound) { 00171 00172 if (fDoReportError) { 00173 fScanner->getValidator()->emitError(XMLValid::IC_UnknownField); 00174 } 00175 00176 return; 00177 } 00178 00179 // store value 00180 if (!fValues.getDatatypeValidatorAt(index) && 00181 !fValues.getValueAt(index)) { 00182 fValuesCount++; 00183 } 00184 00185 fValues.put(field, dv, value); 00186 00187 if (fValuesCount == fValues.size()) { 00188 00189 // is this value as a group duplicated? 00190 if (contains(&fValues)) { 00191 duplicateValue(); 00192 } 00193 00194 // store values 00195 if (!fValueTuples) { 00196 fValueTuples = new (fMemoryManager) RefHashTableOf<FieldValueMap, ICValueHasher>(107, true, ICValueHasher(fMemoryManager), fMemoryManager); 00197 } 00198 00199 FieldValueMap* pICItem = new (fMemoryManager) FieldValueMap(fValues); 00200 fValueTuples->put(pICItem, pICItem); 00201 } 00202 } 00203 00204 void ValueStore::append(const ValueStore* const other) { 00205 00206 if (!other->fValueTuples) { 00207 return; 00208 } 00209 00210 RefHashTableOfEnumerator<FieldValueMap, ICValueHasher> iter(other->fValueTuples, false, fMemoryManager); 00211 while(iter.hasMoreElements()) 00212 { 00213 FieldValueMap& valueMap = iter.nextElement(); 00214 00215 if (!contains(&valueMap)) { 00216 00217 if (!fValueTuples) { 00218 fValueTuples = new (fMemoryManager) RefHashTableOf<FieldValueMap, ICValueHasher>(107, true, ICValueHasher(fMemoryManager), fMemoryManager); 00219 } 00220 00221 FieldValueMap* pICItem = new (fMemoryManager) FieldValueMap(valueMap); 00222 fValueTuples->put(pICItem, pICItem); 00223 } 00224 } 00225 } 00226 00227 void ValueStore::startValueScope() { 00228 00229 fValuesCount = 0; 00230 00231 XMLSize_t count = fIdentityConstraint->getFieldCount(); 00232 00233 for (XMLSize_t i = 0; i < count; i++) { 00234 fValues.put(fIdentityConstraint->getFieldAt(i), 0, 0); 00235 } 00236 } 00237 00238 void ValueStore::endValueScope() { 00239 00240 if (fValuesCount == 0) { 00241 00242 if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEY && fDoReportError) { 00243 fScanner->getValidator()->emitError(XMLValid::IC_AbsentKeyValue, 00244 fIdentityConstraint->getElementName()); 00245 } 00246 00247 return; 00248 } 00249 00250 // do we have enough values? 00251 if ((fValuesCount != fIdentityConstraint->getFieldCount()) && fDoReportError) { 00252 00253 if(fIdentityConstraint->getType()==IdentityConstraint::ICType_KEY) 00254 { 00255 fScanner->getValidator()->emitError(XMLValid::IC_KeyNotEnoughValues, 00256 fIdentityConstraint->getElementName(), fIdentityConstraint->getIdentityConstraintName()); 00257 } 00258 } 00259 } 00260 00261 bool ValueStore::contains(const FieldValueMap* const other) { 00262 00263 if (fValueTuples) 00264 return fValueTuples->get(other)!=0; 00265 00266 return false; 00267 } 00268 00269 void ValueStore::clear() 00270 { 00271 fValuesCount=0; 00272 fValues.clear(); 00273 if(fValueTuples) 00274 fValueTuples->removeAll(); 00275 } 00276 00277 // --------------------------------------------------------------------------- 00278 // ValueStore: Document handling methods 00279 // --------------------------------------------------------------------------- 00280 void ValueStore::endDocumentFragment(ValueStoreCache* const valueStoreCache) { 00281 00282 if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEYREF) { 00283 00284 // verify references 00285 // get the key store corresponding (if it exists): 00286 ValueStore* keyValueStore = valueStoreCache->getGlobalValueStoreFor(((IC_KeyRef*) fIdentityConstraint)->getKey()); 00287 00288 if (!keyValueStore) { 00289 00290 if (fDoReportError) { 00291 fScanner->getValidator()->emitError(XMLValid::IC_KeyRefOutOfScope, 00292 fIdentityConstraint->getIdentityConstraintName()); 00293 } 00294 00295 return; 00296 } 00297 00298 if(fValueTuples) 00299 { 00300 RefHashTableOfEnumerator<FieldValueMap, ICValueHasher> iter(fValueTuples, false, fMemoryManager); 00301 while(iter.hasMoreElements()) 00302 { 00303 FieldValueMap& valueMap = iter.nextElement(); 00304 00305 if (!keyValueStore->contains(&valueMap) && fDoReportError) { 00306 00307 fScanner->getValidator()->emitError(XMLValid::IC_KeyNotFound, 00308 fIdentityConstraint->getElementName()); 00309 } 00310 } 00311 } 00312 } 00313 } 00314 00315 // --------------------------------------------------------------------------- 00316 // ValueStore: Error reporting methods 00317 // --------------------------------------------------------------------------- 00318 void ValueStore::reportNilError(IdentityConstraint* const ic) { 00319 00320 if (fDoReportError && ic->getType() == IdentityConstraint::ICType_KEY) { 00321 fScanner->getValidator()->emitError(XMLValid::IC_KeyMatchesNillable, 00322 ic->getElementName()); 00323 } 00324 } 00325 00326 void ValueStore::duplicateValue() { 00327 00328 if (fDoReportError) { 00329 00330 switch (fIdentityConstraint->getType()) { 00331 case IdentityConstraint::ICType_UNIQUE: 00332 { 00333 fScanner->getValidator()->emitError(XMLValid::IC_DuplicateUnique, 00334 fIdentityConstraint->getElementName()); 00335 break; 00336 } 00337 case IdentityConstraint::ICType_KEY: 00338 { 00339 fScanner->getValidator()->emitError(XMLValid::IC_DuplicateKey, 00340 fIdentityConstraint->getElementName()); 00341 break; 00342 } 00343 } 00344 } 00345 } 00346 00347 XERCES_CPP_NAMESPACE_END 00348