source: icXML/icXML-devel/src/icxercesc/validators/common/GrammarResolver.cpp @ 2734

Last change on this file since 2734 was 2732, checked in by cameron, 7 years ago

icXML version of SchemaSymbols?

File size: 11.7 KB
Line 
1/*
2 * Unless required by applicable law or agreed to in writing, software
3 * distributed under the License is distributed on an "AS IS" BASIS,
4 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5 * See the License for the specific language governing permissions and
6 * limitations under the License.
7 */
8
9/*
10 * $Id $
11 */
12
13#include <icxercesc/validators/common/GrammarResolver.hpp>
14#include <icxercesc/validators/schema/SchemaSymbols.hpp>
15#include <xercesc/validators/schema/SchemaGrammar.hpp>
16#include <xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp>
17#include <xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp>
18#include <icxercesc/framework/XMLGrammarPoolImpl.hpp>
19#include <xercesc/framework/psvi/XSAnnotation.hpp>
20
21XERCES_CPP_NAMESPACE_BEGIN
22
23// ---------------------------------------------------------------------------
24//  GrammarResolver: Constructor and Destructor
25// ---------------------------------------------------------------------------
26GrammarResolver::GrammarResolver(XMLGrammarPool* const gramPool
27                                                           , MemoryManager*  const manager)
28:fCacheGrammar(false)
29,fUseCachedGrammar(false)
30,fGrammarPoolFromExternalApplication(true)
31,fStringPool(0)
32,fGrammarBucket(0)
33,fGrammarFromPool(0)
34,fDataTypeReg(0)
35,fMemoryManager(manager)
36,fGrammarPool(gramPool)
37,fXSModel(0)
38,fGrammarPoolXSModel(0)
39,fGrammarsToAddToXSModel(0)
40{
41        fGrammarBucket = new (manager) RefHashTableOf<Grammar>(29, true,  manager);
42
43        /***
44         * Grammars in this set are not owned
45         */
46        fGrammarFromPool = new (manager) RefHashTableOf<Grammar>(29, false,  manager);
47
48        if (!gramPool)
49        {
50                /***
51                 * We need to instantiate a default grammar pool object so that
52                 * all grammars and grammar components could be created through
53                 * the Factory methods
54                 */
55                fGrammarPool = new (manager) XMLGrammarPoolImpl(manager);
56                fGrammarPoolFromExternalApplication=false;
57        }
58
59        fStringPool = fGrammarPool->getStringPool();
60
61        // REVISIT: size
62        fGrammarsToAddToXSModel = new (manager) ValueVectorOf<SchemaGrammar*> (29, manager);
63}
64
65GrammarResolver::~GrammarResolver()
66{
67        delete fGrammarBucket;
68        delete fGrammarFromPool;
69
70        if (fDataTypeReg)
71          delete fDataTypeReg;
72
73   /***
74        *  delete the grammar pool iff it is created by this resolver
75        */
76   if (!fGrammarPoolFromExternalApplication)
77           delete fGrammarPool;
78
79   if (fXSModel)
80           delete fXSModel;
81   // don't delete fGrammarPoolXSModel! we don't own it!
82   delete fGrammarsToAddToXSModel;
83}
84
85// ---------------------------------------------------------------------------
86//  GrammarResolver: Getter methods
87// ---------------------------------------------------------------------------
88DatatypeValidator*
89GrammarResolver::getDatatypeValidator(const XMLCh* const uriStr,
90                                                                          const XMLCh* const localPartStr) {
91
92        DatatypeValidator* dv = 0;
93
94        if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
95
96                if (!fDataTypeReg) {
97
98                        fDataTypeReg = new (fMemoryManager) DatatypeValidatorFactory(fMemoryManager);
99                }
100
101                dv = fDataTypeReg->getDatatypeValidator(localPartStr);
102        }
103        else {
104
105                Grammar* grammar = getGrammar(uriStr);
106
107                if (grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) {
108
109                        XMLBuffer nameBuf(128, fMemoryManager);
110
111                        nameBuf.set(uriStr);
112                        nameBuf.append(chComma);
113                        nameBuf.append(localPartStr);
114
115                        dv = ((SchemaGrammar*) grammar)->getDatatypeRegistry()->getDatatypeValidator(nameBuf.getRawBuffer());
116                }
117        }
118
119        return dv;
120}
121
122Grammar* GrammarResolver::getGrammar( const XMLCh* const namespaceKey)
123{
124        if (!namespaceKey)
125                return 0;
126
127        Grammar* grammar = fGrammarBucket->get(namespaceKey);
128
129        if (grammar)
130                return grammar;
131
132        if (fUseCachedGrammar)
133        {
134                grammar = fGrammarFromPool->get(namespaceKey);
135                if (grammar)
136                {
137                        return grammar;
138                }
139                else
140                {
141                        XMLSchemaDescription* gramDesc = fGrammarPool->createSchemaDescription(namespaceKey);
142                        Janitor<XMLGrammarDescription> janName(gramDesc);
143                        grammar = fGrammarPool->retrieveGrammar(gramDesc);
144                        if (grammar)
145                        {
146                                fGrammarFromPool->put((void*) grammar->getGrammarDescription()->getGrammarKey(), grammar);
147                        }
148                        return grammar;
149                }
150        }
151
152        return 0;
153}
154
155Grammar* GrammarResolver::getGrammar( XMLGrammarDescription* const gramDesc)
156{
157        if (!gramDesc)
158                return 0;
159
160        Grammar* grammar = fGrammarBucket->get(gramDesc->getGrammarKey());
161
162        if (grammar)
163                return grammar;
164
165        if (fUseCachedGrammar)
166        {
167                grammar = fGrammarFromPool->get(gramDesc->getGrammarKey());
168                if (grammar)
169                {
170                        return grammar;
171                }
172                else
173                {
174                        grammar = fGrammarPool->retrieveGrammar(gramDesc);
175                        if (grammar)
176                        {
177                                fGrammarFromPool->put((void*) grammar->getGrammarDescription()->getGrammarKey(), grammar);
178                        }
179                        return grammar;
180                }
181        }
182
183        return 0;
184}
185
186RefHashTableOfEnumerator<Grammar>
187GrammarResolver::getGrammarEnumerator() const
188{
189        return RefHashTableOfEnumerator<Grammar>(fGrammarBucket, false, fMemoryManager);
190}
191
192RefHashTableOfEnumerator<Grammar>
193GrammarResolver::getReferencedGrammarEnumerator() const
194{
195        return RefHashTableOfEnumerator<Grammar>(fGrammarFromPool, false, fMemoryManager);
196}
197
198RefHashTableOfEnumerator<Grammar>
199GrammarResolver::getCachedGrammarEnumerator() const
200{
201        return fGrammarPool->getGrammarEnumerator();
202}
203
204bool GrammarResolver::containsNameSpace( const XMLCh* const nameSpaceKey )
205{
206        if (!nameSpaceKey)
207                return false;
208        if (fGrammarBucket->containsKey(nameSpaceKey))
209                return true;
210        if (fUseCachedGrammar)
211        {
212                if (fGrammarFromPool->containsKey(nameSpaceKey))
213                        return true;
214
215                // Lastly, need to check in fGrammarPool
216                XMLSchemaDescription* gramDesc = fGrammarPool->createSchemaDescription(nameSpaceKey);
217                Janitor<XMLGrammarDescription> janName(gramDesc);
218                Grammar* grammar = fGrammarPool->retrieveGrammar(gramDesc);
219                if (grammar)
220                        return true;
221        }
222
223        return false;
224}
225
226void GrammarResolver::putGrammar(Grammar* const grammarToAdopt)
227{
228        if (!grammarToAdopt)
229                return;
230
231        /***
232         * the grammar will be either in the grammarpool, or in the grammarbucket
233         */
234        if (!fCacheGrammar || !fGrammarPool->cacheGrammar(grammarToAdopt))
235        {
236                // either we aren't caching or the grammar pool doesn't want it
237                // so we need to look after it
238                fGrammarBucket->put( (void*) grammarToAdopt->getGrammarDescription()->getGrammarKey(), grammarToAdopt );
239                if (grammarToAdopt->getGrammarType() == Grammar::SchemaGrammarType)
240                {
241                        fGrammarsToAddToXSModel->addElement((SchemaGrammar*) grammarToAdopt);
242                }
243        }
244}
245
246// ---------------------------------------------------------------------------
247//  GrammarResolver: methods
248// ---------------------------------------------------------------------------
249void GrammarResolver::reset() {
250        fGrammarBucket->removeAll();
251        fGrammarsToAddToXSModel->removeAllElements();
252        delete fXSModel;
253        fXSModel = 0;
254}
255
256void GrammarResolver::resetCachedGrammar()
257{
258        //REVISIT: if the pool is locked this will fail... should throw an exception?
259        fGrammarPool->clear();
260        // Even though fXSModel and fGrammarPoolXSModel will be invalid don't touch
261        // them here as getXSModel will handle this.
262
263        //to clear all other references to the grammars just deleted from fGrammarPool
264        fGrammarFromPool->removeAll();
265
266}
267
268void GrammarResolver::cacheGrammars()
269{
270        RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarBucket, false, fMemoryManager);
271        ValueVectorOf<XMLCh*> keys(8, fMemoryManager);
272        unsigned int keyCount = 0;
273
274        // Build key set
275        while (grammarEnum.hasMoreElements())
276        {
277                XMLCh* grammarKey = (XMLCh*) grammarEnum.nextElementKey();
278                keys.addElement(grammarKey);
279                keyCount++;
280        }
281
282        // PSVI: assume everything will be added, if caching fails add grammar back
283        //       into vector
284        fGrammarsToAddToXSModel->removeAllElements();
285
286        // Cache
287        for (unsigned int i = 0; i < keyCount; i++)
288        {
289                XMLCh* grammarKey = keys.elementAt(i);
290
291                /***
292                 * It is up to the GrammarPool implementation to handle duplicated grammar
293                 */
294                Grammar* grammar = fGrammarBucket->get(grammarKey);
295                if(fGrammarPool->cacheGrammar(grammar))
296                {
297                        // only orphan grammar if grammar pool accepts caching of it
298                        fGrammarBucket->orphanKey(grammarKey);
299                }
300                else if (grammar->getGrammarType() == Grammar::SchemaGrammarType)
301                {
302                        // add it back to list of grammars not in grammar pool
303                        fGrammarsToAddToXSModel->addElement((SchemaGrammar*) grammar);
304                }
305        }
306
307}
308
309// ---------------------------------------------------------------------------
310//  GrammarResolver: Setter methods
311// ---------------------------------------------------------------------------
312void GrammarResolver::cacheGrammarFromParse(const bool aValue)
313{
314        reset();
315        fCacheGrammar = aValue;
316}
317
318Grammar* GrammarResolver::orphanGrammar(const XMLCh* const nameSpaceKey)
319{
320        if (fCacheGrammar)
321        {
322                Grammar* grammar = fGrammarPool->orphanGrammar(nameSpaceKey);
323                if (grammar)
324                {
325                        if (fGrammarFromPool->containsKey(nameSpaceKey))
326                                fGrammarFromPool->removeKey(nameSpaceKey);
327                }
328                // Check to see if it's in fGrammarBucket, since
329                // we put it there if the grammar pool refused to
330                // cache it.
331                else if (fGrammarBucket->containsKey(nameSpaceKey))
332                {
333                        grammar = fGrammarBucket->orphanKey(nameSpaceKey);
334                }
335
336                return grammar;
337        }
338        else
339        {
340                return fGrammarBucket->orphanKey(nameSpaceKey);
341        }
342}
343
344XSModel *GrammarResolver::getXSModel()
345{
346        XSModel* xsModel;
347        if (fCacheGrammar || fUseCachedGrammar)
348        {
349                // We know if the grammarpool changed thru caching, orphaning and erasing
350                // but NOT by other mechanisms such as lockPool() or unlockPool() so it
351                // is safest to always get it.  The grammarPool XSModel will only be
352                // regenerated if something changed.
353                bool XSModelWasChanged;
354                // The grammarpool will always return an xsmodel, even if it is just
355                // the schema for schema xsmodel...
356                xsModel = fGrammarPool->getXSModel(XSModelWasChanged);
357                if (XSModelWasChanged)
358                {
359                        // we know the grammarpool XSModel has changed or this is the
360                        // first call to getXSModel
361                        if (!fGrammarPoolXSModel && (fGrammarsToAddToXSModel->size() == 0) &&
362                                !fXSModel)
363                        {
364                                fGrammarPoolXSModel = xsModel;
365                                return fGrammarPoolXSModel;
366                        }
367                        else
368                        {
369                                fGrammarPoolXSModel = xsModel;
370                                // We had previously augmented the grammar pool XSModel
371                                // with our our grammars or we would like to upate it now
372                                // so we have to regenerate the XSModel
373                                fGrammarsToAddToXSModel->removeAllElements();
374                                RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarBucket, false, fMemoryManager);
375                                while (grammarEnum.hasMoreElements())
376                                {
377                                        Grammar& grammar = (Grammar&) grammarEnum.nextElement();
378                                        if (grammar.getGrammarType() == Grammar::SchemaGrammarType)
379                                                fGrammarsToAddToXSModel->addElement((SchemaGrammar*)&grammar);
380                                }
381                                delete fXSModel;
382                                if (fGrammarsToAddToXSModel->size())
383                                {
384                                        fXSModel = new (fMemoryManager) XSModel(fGrammarPoolXSModel, this, fMemoryManager);
385                                        fGrammarsToAddToXSModel->removeAllElements();
386                                        return fXSModel;
387                                }
388                                fXSModel = 0;
389                                return fGrammarPoolXSModel;
390                        }
391                }
392                else
393                {
394                        // we know that the grammar pool XSModel is the same as before
395                        if (fGrammarsToAddToXSModel->size())
396                        {
397                                // we need to update our fXSModel with the new grammars
398                                if (fXSModel)
399                                {
400                                        xsModel = new (fMemoryManager) XSModel(fXSModel, this, fMemoryManager);
401                                        fXSModel = xsModel;
402                                }
403                                else
404                                {
405                                        fXSModel = new (fMemoryManager) XSModel(fGrammarPoolXSModel, this, fMemoryManager);
406                                }
407                                fGrammarsToAddToXSModel->removeAllElements();
408                                return fXSModel;
409                        }
410                        // Nothing has changed!
411                        if (fXSModel)
412                        {
413                                return fXSModel;
414                        }
415                        else if (fGrammarPoolXSModel)
416                        {
417                                return fGrammarPoolXSModel;
418                        }
419                        fXSModel = new (fMemoryManager) XSModel(0, this, fMemoryManager);
420                        return fXSModel;
421                }
422        }
423        // Not Caching...
424        if (fGrammarsToAddToXSModel->size())
425        {
426                xsModel = new (fMemoryManager) XSModel(fXSModel, this, fMemoryManager);
427                fGrammarsToAddToXSModel->removeAllElements();
428                fXSModel = xsModel;
429        }
430        else if (!fXSModel)
431        {
432                // create a new model only if we didn't have one already
433                fXSModel = new (fMemoryManager) XSModel(0, this, fMemoryManager);
434        }
435        return fXSModel;
436}
437
438XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.