GME  13
ValueStore.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: 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