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

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

Updates to xercesc sources

File size: 14.4 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: XPathMatcher.cpp 804234 2009-08-14 14:20:16Z amassari $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <xercesc/validators/schema/identity/XPathMatcher.hpp>
26#include <xercesc/validators/schema/identity/XercesXPath.hpp>
27#include <icxercesc/validators/schema/SchemaElementDecl.hpp>
28#include <icxercesc/validators/schema/SchemaAttDef.hpp>
29#include <icxercesc/validators/schema/SchemaSymbols.hpp>
30#include <xercesc/util/RuntimeException.hpp>
31#include <xercesc/util/OutOfMemoryException.hpp>
32#include <xercesc/util/StringPool.hpp>
33#include <xercesc/framework/ValidationContext.hpp>
34
35
36XERCES_CPP_NAMESPACE_BEGIN
37
38typedef JanitorMemFunCall<XPathMatcher>     CleanupType;
39
40// ---------------------------------------------------------------------------
41//  XPathMatcher: Constructors and Destructor
42// ---------------------------------------------------------------------------
43
44
45XPathMatcher::XPathMatcher
46(
47    XercesXPath* const      xpath
48    , XMLStringPool* const  stringPool
49    , MemoryManager* const  manager
50)
51: fLocationPathSize(0)
52, fMatched(0)
53, fNoMatchDepth(0)
54, fCurrentStep(0)
55, fStepIndexes(0)
56, fLocationPaths(0)
57, fIdentityConstraint(0)
58, fStringPool(stringPool)
59, fMemoryManager(manager)
60{
61    CleanupType cleanup(this, &XPathMatcher::cleanUp);
62
63    try {
64        init(xpath);
65    }
66    catch(const OutOfMemoryException&)
67    {
68        cleanup.release();
69
70        throw;
71    }
72
73    cleanup.release();
74}
75
76
77XPathMatcher::XPathMatcher
78(
79    XercesXPath* const          xpath
80    , IdentityConstraint* const ic
81    , XMLStringPool* const      stringPool
82    , MemoryManager* const      manager
83)
84: fLocationPathSize(0)
85, fMatched(0)
86, fNoMatchDepth(0)
87, fCurrentStep(0)
88, fStepIndexes(0)
89, fLocationPaths(0)
90, fIdentityConstraint(ic)
91, fStringPool(stringPool)
92, fMemoryManager(manager)
93{
94    CleanupType cleanup(this, &XPathMatcher::cleanUp);
95
96    try {
97        init(xpath);
98    }
99    catch(const OutOfMemoryException&)
100    {
101        cleanup.release();
102
103        throw;
104    }
105
106    cleanup.release();
107}
108
109
110XPathMatcher::~XPathMatcher()
111{
112    cleanUp();
113}
114
115// ---------------------------------------------------------------------------
116//  XPathMatcher: Helper methods
117// ---------------------------------------------------------------------------
118void XPathMatcher::init(XercesXPath* const xpath) {
119
120    if (xpath) {
121
122        fLocationPaths = xpath->getLocationPaths();
123        fLocationPathSize = (fLocationPaths ? fLocationPaths->size() : 0);
124
125        if (fLocationPathSize) {
126
127            fStepIndexes = new (fMemoryManager) RefVectorOf<ValueStackOf<XMLSize_t> >(fLocationPathSize, true, fMemoryManager);
128            fCurrentStep = (XMLSize_t*) fMemoryManager->allocate
129            (
130                fLocationPathSize * sizeof(XMLSize_t)
131            );//new int[fLocationPathSize];
132            fNoMatchDepth = (XMLSize_t*) fMemoryManager->allocate
133            (
134                fLocationPathSize * sizeof(XMLSize_t)
135            );//new int[fLocationPathSize];
136            fMatched = (unsigned char*) fMemoryManager->allocate
137            (
138                fLocationPathSize * sizeof(unsigned char)
139            );//new int[fLocationPathSize];
140
141            for(XMLSize_t i=0; i < fLocationPathSize; i++) {
142                fStepIndexes->addElement(new (fMemoryManager) ValueStackOf<XMLSize_t>(8, fMemoryManager));
143            }
144        }
145    }
146}
147
148
149// ---------------------------------------------------------------------------
150//  XPathMatcher: XMLDocumentHandler methods
151// ---------------------------------------------------------------------------
152void XPathMatcher::startDocumentFragment() {
153
154    for(XMLSize_t i = 0; i < fLocationPathSize; i++) {
155
156        fStepIndexes->elementAt(i)->removeAllElements();
157        fCurrentStep[i] = 0;
158        fNoMatchDepth[i] = 0;
159        fMatched[i] = 0;
160    }
161}
162
163void XPathMatcher::startElement(const XMLElementDecl& elemDecl,
164                                const unsigned int urlId,
165                                const XMLCh* const elemPrefix,
166                                                                const RefVectorOf<XMLAttr>& attrList,
167                                const XMLSize_t attrCount,
168                                ValidationContext* validationContext /*=0*/) {
169
170    for (XMLSize_t i = 0; i < fLocationPathSize; i++) {
171
172        // push context
173        XMLSize_t startStep = fCurrentStep[i];
174        fStepIndexes->elementAt(i)->push(startStep);
175
176        // try next xpath, if not matching
177        if ((fMatched[i] & XP_MATCHED_D) == XP_MATCHED || fNoMatchDepth[i] > 0) {
178            fNoMatchDepth[i]++;
179            continue;
180        }
181
182        if((fMatched[i] & XP_MATCHED_D) == XP_MATCHED_D) {
183            fMatched[i] = XP_MATCHED_DP;
184        }
185
186        // consume self::node() steps
187        XercesLocationPath* locPath = fLocationPaths->elementAt(i);
188        XMLSize_t stepSize = locPath->getStepSize();
189
190        while (fCurrentStep[i] < stepSize &&
191               locPath->getStep(fCurrentStep[i])->getAxisType() == XercesStep::AxisType_SELF) {
192            fCurrentStep[i]++;
193        }
194
195        if (fCurrentStep[i] == stepSize) {
196
197            fMatched[i] = XP_MATCHED;
198            continue;
199        }
200
201        // now if the current step is a descendant step, we let the next
202        // step do its thing; if it fails, we reset ourselves
203        // to look at this step for next time we're called.
204        // so first consume all descendants:
205        XMLSize_t descendantStep = fCurrentStep[i];
206
207        while (fCurrentStep[i] < stepSize &&
208               locPath->getStep(fCurrentStep[i])->getAxisType() == XercesStep::AxisType_DESCENDANT) {
209            fCurrentStep[i]++;
210        }
211
212        bool sawDescendant = fCurrentStep[i] > descendantStep;
213        if (fCurrentStep[i] == stepSize) {
214
215            fNoMatchDepth[i]++;
216            continue;
217        }
218
219        // match child::... step, if haven't consumed any self::node()
220        if ((fCurrentStep[i] == startStep || fCurrentStep[i] > descendantStep) &&
221            locPath->getStep(fCurrentStep[i])->getAxisType() == XercesStep::AxisType_CHILD) {
222
223            XercesStep* step = locPath->getStep(fCurrentStep[i]);
224            XercesNodeTest* nodeTest = step->getNodeTest();
225
226            QName elemQName(elemPrefix, elemDecl.getElementName()->getLocalPart(), urlId, fStringPool);
227            if (!matches(nodeTest, &elemQName)) {
228
229                if(fCurrentStep[i] > descendantStep) {
230                    fCurrentStep[i] = descendantStep;
231                    continue;
232                }
233
234                fNoMatchDepth[i]++;
235                continue;
236            }
237
238            fCurrentStep[i]++;
239        }
240
241        if (fCurrentStep[i] == stepSize) {
242
243            if (sawDescendant) {
244
245                fCurrentStep[i] = descendantStep;
246                fMatched[i] = XP_MATCHED_D;
247            }
248            else {
249                fMatched[i] = XP_MATCHED;
250            }
251
252            continue;
253        }
254
255        // match attribute::... step
256        if (fCurrentStep[i] < stepSize &&
257            locPath->getStep(fCurrentStep[i])->getAxisType() == XercesStep::AxisType_ATTRIBUTE) {
258
259            if (attrCount) {
260
261                XercesNodeTest* nodeTest = locPath->getStep(fCurrentStep[i])->getNodeTest();
262
263                for (XMLSize_t attrIndex = 0; attrIndex < attrCount; attrIndex++) {
264
265                    const XMLAttr* curDef = attrList.elementAt(attrIndex);
266
267                    if (matches(nodeTest, curDef->getAttName())) {
268
269                        fCurrentStep[i]++;
270
271                        if (fCurrentStep[i] == stepSize) {
272
273                            fMatched[i] = XP_MATCHED_A;
274
275                            SchemaAttDef* attDef = ((SchemaElementDecl&) elemDecl).getAttDef(curDef->getName(), curDef->getURIId());
276                            DatatypeValidator* dv = (attDef) ? attDef->getDatatypeValidator() : 0;
277                            const XMLCh* value = curDef->getValue();
278                            // store QName using their Clark name
279                            if (dv && dv->getType()==DatatypeValidator::QName)
280                            {
281                                int index=XMLString::indexOf(value, chColon);
282                                if(index==-1)
283                                    matched(value, dv, false);
284                                else
285                                {
286                                    XMLBuffer buff(1023, fMemoryManager);
287                                    buff.append(chOpenCurly);
288                                    if(validationContext)
289                                    {
290                                        XMLCh* prefix=(XMLCh*)fMemoryManager->allocate((index+1)*sizeof(XMLCh));
291                                        ArrayJanitor<XMLCh> janPrefix(prefix, fMemoryManager);
292                                        XMLString::subString(prefix, value, 0, (XMLSize_t)index, fMemoryManager);
293                                        buff.append(validationContext->getURIForPrefix(prefix));
294                                    }
295                                    buff.append(chCloseCurly);
296                                    buff.append(value+index+1);
297                                    matched(buff.getRawBuffer(), dv, false);
298                                }
299                            }
300                            else
301                            {
302                                matched(value, dv, false);
303                            }
304                        }
305                        break;
306                    }
307                }
308            }
309
310            if ((fMatched[i] & XP_MATCHED) != XP_MATCHED) {
311
312                if(fCurrentStep[i] > descendantStep) {
313
314                    fCurrentStep[i] = descendantStep;
315                    continue;
316                }
317
318                fNoMatchDepth[i]++;
319            }
320        }
321    }
322}
323
324void XPathMatcher::endElement(const XMLElementDecl& elemDecl,
325                              const XMLCh* const elemContent,
326                              ValidationContext* validationContext /*=0*/,
327                              DatatypeValidator* actualValidator /*=0*/) {
328
329    for(XMLSize_t i = 0; i < fLocationPathSize; i++) {
330
331        // go back a step
332        fCurrentStep[i] = fStepIndexes->elementAt(i)->pop();
333
334        // don't do anything, if not matching
335        if (fNoMatchDepth[i] > 0) {
336            fNoMatchDepth[i]--;
337        }
338        // signal match, if appropriate
339        else {
340
341            if (fMatched[i] == 0)
342                continue;
343           
344            if ((fMatched[i] & XP_MATCHED_A) == XP_MATCHED_A) {
345                fMatched[i] = 0;
346                continue;
347            }
348
349            DatatypeValidator* dv = actualValidator?actualValidator:((SchemaElementDecl*) &elemDecl)->getDatatypeValidator();
350            bool isNillable = (((SchemaElementDecl *) &elemDecl)->getMiscFlags() & SchemaSymbols::XSD_NILLABLE) != 0;
351
352            // store QName using their Clark name
353            if(dv && dv->getType()==DatatypeValidator::QName)
354            {
355                int index=XMLString::indexOf(elemContent, chColon);
356                if(index==-1)
357                    matched(elemContent, dv, isNillable);
358                else
359                {
360                    XMLBuffer buff(1023, fMemoryManager);
361                    buff.append(chOpenCurly);
362                    if (validationContext)
363                    {
364                        XMLCh* prefix=(XMLCh*)fMemoryManager->allocate((index+1)*sizeof(XMLCh));
365                        ArrayJanitor<XMLCh> janPrefix(prefix, fMemoryManager);
366                        XMLString::subString(prefix, elemContent, 0, (XMLSize_t)index, fMemoryManager);
367                        buff.append(validationContext->getURIForPrefix(prefix));
368                    }
369                    buff.append(chCloseCurly);
370                    buff.append(elemContent+index+1);
371                    matched(buff.getRawBuffer(), dv, isNillable);
372                }
373            }
374            else
375                matched(elemContent, dv, isNillable);
376            fMatched[i] = 0;
377        }
378    }
379}
380
381
382// ---------------------------------------------------------------------------
383//  XPathMatcher: Match methods
384// ---------------------------------------------------------------------------
385unsigned char XPathMatcher::isMatched() {
386
387    // xpath has been matched if any one of the members of the union have matched.
388    for (XMLSize_t i=0; i < fLocationPathSize; i++) {
389        if (((fMatched[i] & XP_MATCHED) == XP_MATCHED)
390            && ((fMatched[i] & XP_MATCHED_DP) != XP_MATCHED_DP))
391            return fMatched[i];
392    }
393
394    return 0;
395}
396
397void XPathMatcher::matched(const XMLCh* const,
398                           DatatypeValidator* const,
399                           const bool) {
400    return;
401}
402
403bool XPathMatcher::matches(const XercesNodeTest* nodeTest, const QName* qName)
404{
405    if (nodeTest->getType() == XercesNodeTest::NodeType_QNAME) {
406        return (*nodeTest->getName())==(*qName);
407    }
408    if (nodeTest->getType() == XercesNodeTest::NodeType_NAMESPACE) {
409        return nodeTest->getName()->getURI() == qName->getURI();
410    }
411    // NodeType_WILDCARD
412    return true;
413}
414
415// ---------------------------------------------------------------------------
416//  XPathMatcher: Match methods
417// ---------------------------------------------------------------------------
418int XPathMatcher::getInitialDepth() const
419{
420    ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Regex_NotSupported, fMemoryManager);
421    return 0; // to make some compilers happy
422}
423
424XPathMatcher::XPathMatcher( XercesXPath* const, MemoryManager* const)
425{
426    DEPRECATED_FEATURE_IN_ICXML;
427}
428
429
430XPathMatcher::XPathMatcher(XercesXPath* const, IdentityConstraint* const, MemoryManager* const)
431{
432    DEPRECATED_FEATURE_IN_ICXML;
433}
434
435
436XERCES_CPP_NAMESPACE_END
437
438/**
439  * End of file XPathMatcher.cpp
440  */
441
Note: See TracBrowser for help on using the repository browser.