source: icXML/icXML-devel/src/xercesc/validators/schema/identity/ValueStore.cpp @ 3565

Last change on this file since 3565 was 2722, checked in by cameron, 7 years ago

Original Xerces files with import mods for icxercesc

File size: 10.9 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: ValueStore.cpp 804209 2009-08-14 13:15:05Z amassari $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <icxercesc/internal/XMLScanner.hpp>
26#include <icxercesc/framework/XMLValidator.hpp>
27#include <xercesc/validators/datatype/DatatypeValidator.hpp>
28#include <xercesc/validators/schema/identity/FieldActivator.hpp>
29#include <xercesc/validators/schema/identity/ValueStore.hpp>
30#include <xercesc/validators/schema/identity/IC_Field.hpp>
31#include <xercesc/validators/schema/identity/IC_KeyRef.hpp>
32#include <xercesc/validators/schema/identity/ValueStoreCache.hpp>
33
34XERCES_CPP_NAMESPACE_BEGIN
35
36//
37// ---------------------------------------------------------------------------
38// ICValueHasher: the hasher for identity constraints values
39// ---------------------------------------------------------------------------
40XMLSize_t ICValueHasher::getHashVal(const void* key, XMLSize_t mod) const
41{
42    const FieldValueMap* valueMap=(const FieldValueMap*)key;
43    XMLSize_t hashVal = 0;
44
45    XMLSize_t size = valueMap->size();
46    for (XMLSize_t j=0; j<size; j++) {
47        // reach the most generic datatype validator
48        DatatypeValidator* dv = valueMap->getDatatypeValidatorAt(j);
49        while(dv && dv->getBaseValidator())
50            dv = dv->getBaseValidator();
51        const XMLCh* const val = valueMap->getValueAt(j);
52        const XMLCh* canonVal = (dv && val)?dv->getCanonicalRepresentation(val, fMemoryManager):0;
53        if(canonVal)
54        {
55            hashVal += XMLString::hash(canonVal, mod);
56            fMemoryManager->deallocate((void*)canonVal);
57        }
58        else if(val)
59            hashVal += XMLString::hash(val, mod);
60    }
61
62    return hashVal % mod;
63}
64
65bool ICValueHasher::equals(const void *const key1, const void *const key2) const
66{
67    const FieldValueMap* left=(const FieldValueMap*)key1;
68    const FieldValueMap* right=(const FieldValueMap*)key2;
69
70    XMLSize_t lSize = left->size();
71    XMLSize_t rSize = right->size();
72    if (lSize == rSize) 
73    {
74        bool matchFound = true;
75
76        for (XMLSize_t j=0; j<rSize; j++) {
77            if (!isDuplicateOf(left->getDatatypeValidatorAt(j), left->getValueAt(j),
78                               right->getDatatypeValidatorAt(j), right->getValueAt(j))) {
79                matchFound = false;
80                break;
81            }
82        }
83
84        if (matchFound) { // found it
85            return true;
86        }
87    }
88    return false;
89}
90
91bool ICValueHasher::isDuplicateOf(DatatypeValidator* const dv1, const XMLCh* const val1,
92                                  DatatypeValidator* const dv2, const XMLCh* const val2) const 
93{
94
95    // if either validator's null, fall back on string comparison
96    if(!dv1 || !dv2) {
97        return (XMLString::equals(val1, val2));
98    }
99
100    bool val1IsEmpty = (val1==0 || *val1==0);
101    bool val2IsEmpty = (val2==0 || *val2==0);
102
103    if (val1IsEmpty && val2IsEmpty) {
104
105        if (dv1 == dv2) {
106            return true;
107        }
108
109        return false;
110    }
111
112    if (val1IsEmpty || val2IsEmpty) {
113        return false;
114    }
115
116    // find the common ancestor, if there is one
117    DatatypeValidator* tempVal1 = dv1;
118    while(tempVal1)
119    {
120        DatatypeValidator* tempVal2 = dv2;
121        for(; tempVal2 != NULL && tempVal2 != tempVal1; tempVal2 = tempVal2->getBaseValidator()) ;
122        if (tempVal2) 
123            return ((tempVal2->compare(val1, val2, fMemoryManager)) == 0);
124        tempVal1=tempVal1->getBaseValidator();
125    }
126
127    // if we're here it means the types weren't related. They are different:
128    return false;
129}
130
131// ---------------------------------------------------------------------------
132//  ValueStore: Constructors and Destructor
133// ---------------------------------------------------------------------------
134ValueStore::ValueStore(IdentityConstraint* const ic,
135                       XMLScanner* const scanner,
136                       MemoryManager* const manager)
137    : fDoReportError(false)
138    , fValuesCount(0)
139    , fIdentityConstraint(ic)
140    , fValues(manager)
141    , fValueTuples(0)
142    , fScanner(scanner)
143    , fMemoryManager(manager)
144{
145    fDoReportError = (scanner && (scanner->getValidationScheme() == XMLScanner::Val_Always));
146}
147
148
149ValueStore::~ValueStore()
150{
151    delete fValueTuples;
152}
153
154// ---------------------------------------------------------------------------
155//  ValueStore: Helper methods
156// ---------------------------------------------------------------------------
157void ValueStore::addValue(FieldActivator* const fieldActivator,
158                          IC_Field* const field,
159                          DatatypeValidator* const dv,
160                          const XMLCh* const value) {
161
162    if (!fieldActivator->getMayMatch(field) && fDoReportError) {
163        fScanner->getValidator()->emitError(XMLValid::IC_FieldMultipleMatch);
164    }
165
166    // do we even know this field?
167    XMLSize_t index;
168    bool bFound = fValues.indexOf(field, index);
169
170    if (!bFound) {
171
172        if (fDoReportError) {
173           fScanner->getValidator()->emitError(XMLValid::IC_UnknownField);
174        }
175
176        return;
177    }
178
179    // store value
180    if (!fValues.getDatatypeValidatorAt(index) &&
181        !fValues.getValueAt(index)) {
182        fValuesCount++;
183    }
184
185    fValues.put(field, dv, value);
186
187    if (fValuesCount == fValues.size()) {
188
189        // is this value as a group duplicated?
190        if (contains(&fValues)) {
191            duplicateValue();
192        }
193
194        // store values
195        if (!fValueTuples) {
196            fValueTuples = new (fMemoryManager) RefHashTableOf<FieldValueMap, ICValueHasher>(107, true, ICValueHasher(fMemoryManager), fMemoryManager);
197        }
198
199        FieldValueMap* pICItem = new (fMemoryManager) FieldValueMap(fValues);
200        fValueTuples->put(pICItem, pICItem);
201    }
202}
203
204void ValueStore::append(const ValueStore* const other) {
205
206    if (!other->fValueTuples) {
207        return;
208    }
209
210    RefHashTableOfEnumerator<FieldValueMap, ICValueHasher> iter(other->fValueTuples, false, fMemoryManager);
211    while(iter.hasMoreElements())
212    {
213        FieldValueMap& valueMap = iter.nextElement();
214
215        if (!contains(&valueMap)) {
216
217            if (!fValueTuples) {
218                fValueTuples = new (fMemoryManager) RefHashTableOf<FieldValueMap, ICValueHasher>(107, true, ICValueHasher(fMemoryManager), fMemoryManager);
219            }
220
221            FieldValueMap* pICItem = new (fMemoryManager) FieldValueMap(valueMap);
222            fValueTuples->put(pICItem, pICItem);
223        }
224    }
225}
226
227void ValueStore::startValueScope() {
228
229    fValuesCount = 0;
230
231    XMLSize_t count = fIdentityConstraint->getFieldCount();
232
233    for (XMLSize_t i = 0; i < count; i++) {
234        fValues.put(fIdentityConstraint->getFieldAt(i), 0, 0);
235    }
236}
237
238void ValueStore::endValueScope() {
239
240    if (fValuesCount == 0) {
241
242        if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEY && fDoReportError) {
243            fScanner->getValidator()->emitError(XMLValid::IC_AbsentKeyValue,
244                fIdentityConstraint->getElementName());
245        }
246
247        return;
248    }
249
250    // do we have enough values?
251    if ((fValuesCount != fIdentityConstraint->getFieldCount()) && fDoReportError) {
252
253        if(fIdentityConstraint->getType()==IdentityConstraint::ICType_KEY)
254        {
255                        fScanner->getValidator()->emitError(XMLValid::IC_KeyNotEnoughValues,
256                fIdentityConstraint->getElementName(), fIdentityConstraint->getIdentityConstraintName());
257        }
258    }
259}
260
261bool ValueStore::contains(const FieldValueMap* const other) {
262
263    if (fValueTuples)
264        return fValueTuples->get(other)!=0;
265
266    return false;
267}
268
269void ValueStore::clear()
270{
271    fValuesCount=0;
272    fValues.clear();
273    if(fValueTuples)
274        fValueTuples->removeAll();
275}
276
277// ---------------------------------------------------------------------------
278//  ValueStore: Document handling methods
279// ---------------------------------------------------------------------------
280void ValueStore::endDocumentFragment(ValueStoreCache* const valueStoreCache) {
281
282    if (fIdentityConstraint->getType() == IdentityConstraint::ICType_KEYREF) {
283
284        // verify references
285        // get the key store corresponding (if it exists):
286        ValueStore* keyValueStore = valueStoreCache->getGlobalValueStoreFor(((IC_KeyRef*) fIdentityConstraint)->getKey());
287
288        if (!keyValueStore) {
289
290            if (fDoReportError) {
291                fScanner->getValidator()->emitError(XMLValid::IC_KeyRefOutOfScope,
292                    fIdentityConstraint->getIdentityConstraintName());
293            }
294
295            return;
296        }
297
298        if(fValueTuples)
299        {
300            RefHashTableOfEnumerator<FieldValueMap, ICValueHasher> iter(fValueTuples, false, fMemoryManager);
301            while(iter.hasMoreElements())
302            {
303                FieldValueMap& valueMap = iter.nextElement();
304
305                if (!keyValueStore->contains(&valueMap) && fDoReportError) {
306
307                    fScanner->getValidator()->emitError(XMLValid::IC_KeyNotFound,
308                        fIdentityConstraint->getElementName());
309                }
310            }
311        }
312    }
313}
314
315// ---------------------------------------------------------------------------
316//  ValueStore: Error reporting methods
317// ---------------------------------------------------------------------------
318void ValueStore::reportNilError(IdentityConstraint* const ic) {
319
320    if (fDoReportError && ic->getType() == IdentityConstraint::ICType_KEY) {
321        fScanner->getValidator()->emitError(XMLValid::IC_KeyMatchesNillable,
322                                            ic->getElementName());
323    }
324}
325
326void ValueStore::duplicateValue() {
327
328    if (fDoReportError) {
329
330        switch (fIdentityConstraint->getType()) {
331        case IdentityConstraint::ICType_UNIQUE:
332            {
333                fScanner->getValidator()->emitError(XMLValid::IC_DuplicateUnique,
334                    fIdentityConstraint->getElementName());
335                break;
336            }
337        case IdentityConstraint::ICType_KEY:
338            {
339                fScanner->getValidator()->emitError(XMLValid::IC_DuplicateKey,
340                    fIdentityConstraint->getElementName());
341                break;
342            }
343        }
344    }
345}
346
347XERCES_CPP_NAMESPACE_END
348
349/**
350  * End of file ValueStore.cpp
351  */
352
Note: See TracBrowser for help on using the repository browser.