GME  13
GrammarResolver.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 $
00020  */
00021 
00022 #include <xercesc/validators/common/GrammarResolver.hpp>
00023 #include <xercesc/validators/schema/SchemaSymbols.hpp>
00024 #include <xercesc/validators/schema/SchemaGrammar.hpp>
00025 #include <xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp>
00026 #include <xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp>
00027 #include <xercesc/framework/XMLGrammarPoolImpl.hpp>
00028 #include <xercesc/framework/psvi/XSAnnotation.hpp>
00029 
00030 XERCES_CPP_NAMESPACE_BEGIN
00031 
00032 // ---------------------------------------------------------------------------
00033 //  GrammarResolver: Constructor and Destructor
00034 // ---------------------------------------------------------------------------
00035 GrammarResolver::GrammarResolver(XMLGrammarPool* const gramPool
00036                                , MemoryManager*  const manager)
00037 :fCacheGrammar(false)
00038 ,fUseCachedGrammar(false)
00039 ,fGrammarPoolFromExternalApplication(true)
00040 ,fStringPool(0)
00041 ,fGrammarBucket(0)
00042 ,fGrammarFromPool(0)
00043 ,fDataTypeReg(0)
00044 ,fMemoryManager(manager)
00045 ,fGrammarPool(gramPool)
00046 ,fXSModel(0)
00047 ,fGrammarPoolXSModel(0)
00048 ,fGrammarsToAddToXSModel(0)
00049 {
00050     fGrammarBucket = new (manager) RefHashTableOf<Grammar>(29, true,  manager);
00051 
00052     /***
00053      * Grammars in this set are not owned
00054      */    
00055     fGrammarFromPool = new (manager) RefHashTableOf<Grammar>(29, false,  manager);
00056 
00057     if (!gramPool)
00058     {
00059         /***
00060          * We need to instantiate a default grammar pool object so that
00061          * all grammars and grammar components could be created through
00062          * the Factory methods
00063          */
00064         fGrammarPool = new (manager) XMLGrammarPoolImpl(manager);     
00065         fGrammarPoolFromExternalApplication=false;
00066     }
00067     fStringPool = fGrammarPool->getURIStringPool();
00068 
00069     // REVISIT: size
00070     fGrammarsToAddToXSModel = new (manager) ValueVectorOf<SchemaGrammar*> (29, manager);
00071 }
00072 
00073 GrammarResolver::~GrammarResolver()
00074 {  
00075     delete fGrammarBucket;
00076     delete fGrammarFromPool;
00077 
00078     if (fDataTypeReg)
00079       delete fDataTypeReg;
00080 
00081    /***
00082     *  delete the grammar pool iff it is created by this resolver
00083     */
00084    if (!fGrammarPoolFromExternalApplication)
00085        delete fGrammarPool;
00086 
00087    if (fXSModel)
00088        delete fXSModel;
00089    // don't delete fGrammarPoolXSModel! we don't own it!
00090    delete fGrammarsToAddToXSModel;
00091 }
00092 
00093 // ---------------------------------------------------------------------------
00094 //  GrammarResolver: Getter methods
00095 // ---------------------------------------------------------------------------
00096 DatatypeValidator*
00097 GrammarResolver::getDatatypeValidator(const XMLCh* const uriStr,
00098                                       const XMLCh* const localPartStr) {
00099 
00100     DatatypeValidator* dv = 0;
00101 
00102     if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
00103 
00104         if (!fDataTypeReg) {
00105 
00106             fDataTypeReg = new (fMemoryManager) DatatypeValidatorFactory(fMemoryManager);
00107         }
00108 
00109         dv = fDataTypeReg->getDatatypeValidator(localPartStr);
00110     }
00111     else {
00112 
00113         Grammar* grammar = getGrammar(uriStr);
00114 
00115         if (grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) {
00116 
00117             XMLBuffer nameBuf(128, fMemoryManager);
00118 
00119             nameBuf.set(uriStr);
00120             nameBuf.append(chComma);
00121             nameBuf.append(localPartStr);
00122 
00123             dv = ((SchemaGrammar*) grammar)->getDatatypeRegistry()->getDatatypeValidator(nameBuf.getRawBuffer());
00124         }
00125     }
00126 
00127     return dv;
00128 }
00129 
00130 Grammar* GrammarResolver::getGrammar( const XMLCh* const namespaceKey)
00131 {
00132     if (!namespaceKey)
00133         return 0;
00134 
00135     Grammar* grammar = fGrammarBucket->get(namespaceKey);
00136 
00137     if (grammar)
00138         return grammar;
00139 
00140     if (fUseCachedGrammar)
00141     {
00142         grammar = fGrammarFromPool->get(namespaceKey);
00143         if (grammar)
00144         {
00145             return grammar;
00146         }
00147         else
00148         {
00149             XMLSchemaDescription* gramDesc = fGrammarPool->createSchemaDescription(namespaceKey);
00150             Janitor<XMLGrammarDescription> janName(gramDesc);
00151             grammar = fGrammarPool->retrieveGrammar(gramDesc);
00152             if (grammar)
00153             {
00154                 fGrammarFromPool->put((void*) grammar->getGrammarDescription()->getGrammarKey(), grammar);
00155             }
00156             return grammar;
00157         }
00158     }
00159 
00160     return 0;
00161 }
00162 
00163 Grammar* GrammarResolver::getGrammar( XMLGrammarDescription* const gramDesc)
00164 {
00165     if (!gramDesc)
00166         return 0;
00167 
00168     Grammar* grammar = fGrammarBucket->get(gramDesc->getGrammarKey());
00169 
00170     if (grammar)
00171         return grammar;
00172 
00173     if (fUseCachedGrammar)
00174     {
00175         grammar = fGrammarFromPool->get(gramDesc->getGrammarKey());
00176         if (grammar)
00177         {
00178             return grammar;
00179         }
00180         else
00181         {
00182             grammar = fGrammarPool->retrieveGrammar(gramDesc);
00183             if (grammar)
00184             {
00185                 fGrammarFromPool->put((void*) grammar->getGrammarDescription()->getGrammarKey(), grammar);
00186             }
00187             return grammar;
00188         }
00189     }
00190 
00191     return 0;
00192 }
00193 
00194 RefHashTableOfEnumerator<Grammar>
00195 GrammarResolver::getGrammarEnumerator() const
00196 {
00197     return RefHashTableOfEnumerator<Grammar>(fGrammarBucket, false, fMemoryManager);
00198 }
00199 
00200 RefHashTableOfEnumerator<Grammar>
00201 GrammarResolver::getReferencedGrammarEnumerator() const
00202 {
00203     return RefHashTableOfEnumerator<Grammar>(fGrammarFromPool, false, fMemoryManager);
00204 }
00205 
00206 RefHashTableOfEnumerator<Grammar>
00207 GrammarResolver::getCachedGrammarEnumerator() const
00208 {
00209     return fGrammarPool->getGrammarEnumerator();
00210 }
00211 
00212 bool GrammarResolver::containsNameSpace( const XMLCh* const nameSpaceKey )
00213 {
00214     if (!nameSpaceKey)
00215         return false;
00216     if (fGrammarBucket->containsKey(nameSpaceKey))
00217         return true;
00218     if (fUseCachedGrammar)
00219     {
00220         if (fGrammarFromPool->containsKey(nameSpaceKey))
00221             return true;
00222 
00223         // Lastly, need to check in fGrammarPool        
00224         XMLSchemaDescription* gramDesc = fGrammarPool->createSchemaDescription(nameSpaceKey);
00225         Janitor<XMLGrammarDescription> janName(gramDesc);
00226         Grammar* grammar = fGrammarPool->retrieveGrammar(gramDesc);
00227         if (grammar)
00228             return true;
00229     }
00230 
00231     return false;
00232 }
00233 
00234 void GrammarResolver::putGrammar(Grammar* const grammarToAdopt)
00235 {
00236     if (!grammarToAdopt)
00237         return;
00238 
00239     /***
00240      * the grammar will be either in the grammarpool, or in the grammarbucket
00241      */
00242     if (!fCacheGrammar || !fGrammarPool->cacheGrammar(grammarToAdopt))
00243     {
00244         // either we aren't caching or the grammar pool doesn't want it
00245         // so we need to look after it
00246         fGrammarBucket->put( (void*) grammarToAdopt->getGrammarDescription()->getGrammarKey(), grammarToAdopt );
00247         if (grammarToAdopt->getGrammarType() == Grammar::SchemaGrammarType)
00248         {
00249             fGrammarsToAddToXSModel->addElement((SchemaGrammar*) grammarToAdopt);
00250         }
00251     }
00252 }
00253 
00254 // ---------------------------------------------------------------------------
00255 //  GrammarResolver: methods
00256 // ---------------------------------------------------------------------------
00257 void GrammarResolver::reset() {
00258     fGrammarBucket->removeAll();
00259     fGrammarsToAddToXSModel->removeAllElements();
00260     delete fXSModel;
00261     fXSModel = 0;
00262 }
00263 
00264 void GrammarResolver::resetCachedGrammar()
00265 {
00266     //REVISIT: if the pool is locked this will fail... should throw an exception?
00267     fGrammarPool->clear();
00268     // Even though fXSModel and fGrammarPoolXSModel will be invalid don't touch 
00269     // them here as getXSModel will handle this.
00270 
00271     //to clear all other references to the grammars just deleted from fGrammarPool
00272     fGrammarFromPool->removeAll(); 
00273 
00274 }
00275 
00276 void GrammarResolver::cacheGrammars()
00277 {
00278     RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarBucket, false, fMemoryManager);
00279     ValueVectorOf<XMLCh*> keys(8, fMemoryManager);
00280     unsigned int keyCount = 0;
00281 
00282     // Build key set
00283     while (grammarEnum.hasMoreElements()) 
00284     {
00285         XMLCh* grammarKey = (XMLCh*) grammarEnum.nextElementKey();
00286         keys.addElement(grammarKey);
00287         keyCount++;
00288     }
00289 
00290     // PSVI: assume everything will be added, if caching fails add grammar back 
00291     //       into vector
00292     fGrammarsToAddToXSModel->removeAllElements();
00293 
00294     // Cache
00295     for (unsigned int i = 0; i < keyCount; i++) 
00296     {
00297         XMLCh* grammarKey = keys.elementAt(i);    
00298 
00299         /***
00300          * It is up to the GrammarPool implementation to handle duplicated grammar
00301          */
00302         Grammar* grammar = fGrammarBucket->get(grammarKey);
00303         if(fGrammarPool->cacheGrammar(grammar))
00304         {
00305             // only orphan grammar if grammar pool accepts caching of it
00306             fGrammarBucket->orphanKey(grammarKey);
00307         }
00308         else if (grammar->getGrammarType() == Grammar::SchemaGrammarType)
00309         {
00310             // add it back to list of grammars not in grammar pool
00311             fGrammarsToAddToXSModel->addElement((SchemaGrammar*) grammar);           
00312         }
00313     }
00314 
00315 }
00316 
00317 // ---------------------------------------------------------------------------
00318 //  GrammarResolver: Setter methods
00319 // ---------------------------------------------------------------------------
00320 void GrammarResolver::cacheGrammarFromParse(const bool aValue)
00321 {
00322     reset();
00323     fCacheGrammar = aValue;
00324 }
00325 
00326 Grammar* GrammarResolver::orphanGrammar(const XMLCh* const nameSpaceKey)
00327 {
00328     if (fCacheGrammar)
00329     {
00330         Grammar* grammar = fGrammarPool->orphanGrammar(nameSpaceKey);
00331         if (grammar)
00332         {
00333             if (fGrammarFromPool->containsKey(nameSpaceKey))
00334                 fGrammarFromPool->removeKey(nameSpaceKey);
00335         }
00336         // Check to see if it's in fGrammarBucket, since
00337         // we put it there if the grammar pool refused to
00338         // cache it.
00339         else if (fGrammarBucket->containsKey(nameSpaceKey))
00340         {
00341             grammar = fGrammarBucket->orphanKey(nameSpaceKey);
00342         }
00343 
00344         return grammar;
00345     }
00346     else
00347     {
00348         return fGrammarBucket->orphanKey(nameSpaceKey);
00349     }
00350 }
00351 
00352 XSModel *GrammarResolver::getXSModel()
00353 {
00354     XSModel* xsModel;
00355     if (fCacheGrammar || fUseCachedGrammar)
00356     {
00357         // We know if the grammarpool changed thru caching, orphaning and erasing
00358         // but NOT by other mechanisms such as lockPool() or unlockPool() so it
00359         // is safest to always get it.  The grammarPool XSModel will only be 
00360         // regenerated if something changed.
00361         bool XSModelWasChanged;
00362         // The grammarpool will always return an xsmodel, even if it is just
00363         // the schema for schema xsmodel...
00364         xsModel = fGrammarPool->getXSModel(XSModelWasChanged);
00365         if (XSModelWasChanged)
00366         {
00367             // we know the grammarpool XSModel has changed or this is the
00368             // first call to getXSModel
00369             if (!fGrammarPoolXSModel && (fGrammarsToAddToXSModel->size() == 0) &&
00370                 !fXSModel)
00371             { 
00372                 fGrammarPoolXSModel = xsModel;
00373                 return fGrammarPoolXSModel;
00374             }
00375             else
00376             {
00377                 fGrammarPoolXSModel = xsModel;
00378                 // We had previously augmented the grammar pool XSModel
00379                 // with our our grammars or we would like to upate it now
00380                 // so we have to regenerate the XSModel
00381                 fGrammarsToAddToXSModel->removeAllElements();
00382                 RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarBucket, false, fMemoryManager);
00383                 while (grammarEnum.hasMoreElements()) 
00384                 {
00385                     Grammar& grammar = (Grammar&) grammarEnum.nextElement();
00386                     if (grammar.getGrammarType() == Grammar::SchemaGrammarType)
00387                         fGrammarsToAddToXSModel->addElement((SchemaGrammar*)&grammar);
00388                 }
00389                 delete fXSModel;
00390                 if (fGrammarsToAddToXSModel->size())
00391                 {                    
00392                     fXSModel = new (fMemoryManager) XSModel(fGrammarPoolXSModel, this, fMemoryManager);
00393                     fGrammarsToAddToXSModel->removeAllElements();
00394                     return fXSModel;
00395                 }       
00396                 fXSModel = 0; 
00397                 return fGrammarPoolXSModel;                                                      
00398             }       
00399         }
00400         else {
00401             // we know that the grammar pool XSModel is the same as before
00402             if (fGrammarsToAddToXSModel->size())
00403             {
00404                 // we need to update our fXSModel with the new grammars               
00405                 if (fXSModel)
00406                 {
00407                     xsModel = new (fMemoryManager) XSModel(fXSModel, this, fMemoryManager);                   
00408                     fXSModel = xsModel;
00409                 }
00410                 else
00411                 {
00412                     fXSModel = new (fMemoryManager) XSModel(fGrammarPoolXSModel, this, fMemoryManager);
00413                 }
00414                 fGrammarsToAddToXSModel->removeAllElements();
00415                 return fXSModel;
00416             }
00417             // Nothing has changed!
00418             if (fXSModel)
00419             {
00420                 return fXSModel;
00421             }
00422             else if (fGrammarPoolXSModel)
00423             {
00424                 return fGrammarPoolXSModel;
00425             }
00426             fXSModel = new (fMemoryManager) XSModel(0, this, fMemoryManager);    
00427             return fXSModel;    
00428         }
00429     }
00430     // Not Caching...
00431     if (fGrammarsToAddToXSModel->size())
00432     {      
00433         xsModel = new (fMemoryManager) XSModel(fXSModel, this, fMemoryManager);
00434         fGrammarsToAddToXSModel->removeAllElements();
00435         fXSModel = xsModel;             
00436     }
00437     else if (!fXSModel)
00438     {
00439         // create a new model only if we didn't have one already
00440         fXSModel = new (fMemoryManager) XSModel(0, this, fMemoryManager);
00441     }
00442     return fXSModel; 
00443 }
00444 
00445 XERCES_CPP_NAMESPACE_END