GME
13
|
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: DTDElementDecl.cpp 471747 2006-11-06 14:31:56Z amassari $ 00020 */ 00021 00022 00023 // --------------------------------------------------------------------------- 00024 // Includes 00025 // --------------------------------------------------------------------------- 00026 #include <xercesc/util/XMLString.hpp> 00027 #include <xercesc/util/XMLUniDefs.hpp> 00028 #include <xercesc/util/XMLUni.hpp> 00029 #include <xercesc/framework/XMLBuffer.hpp> 00030 #include <xercesc/validators/common/DFAContentModel.hpp> 00031 #include <xercesc/validators/common/ContentSpecNode.hpp> 00032 #include <xercesc/validators/common/MixedContentModel.hpp> 00033 #include <xercesc/validators/common/SimpleContentModel.hpp> 00034 #include <xercesc/validators/DTD/DTDAttDefList.hpp> 00035 #include <xercesc/validators/DTD/DTDElementDecl.hpp> 00036 00037 #include <xercesc/internal/XTemplateSerializer.hpp> 00038 00039 XERCES_CPP_NAMESPACE_BEGIN 00040 00041 // --------------------------------------------------------------------------- 00042 // DTDElementDecl: Constructors and Destructor 00043 // --------------------------------------------------------------------------- 00044 DTDElementDecl::DTDElementDecl(MemoryManager* const manager) : 00045 00046 XMLElementDecl(manager) 00047 , fModelType(Any) 00048 , fAttDefs(0) 00049 , fAttList(0) 00050 , fContentSpec(0) 00051 , fContentModel(0) 00052 , fFormattedModel(0) 00053 { 00054 } 00055 00056 DTDElementDecl::DTDElementDecl( const XMLCh* const elemRawName 00057 , const unsigned int uriId 00058 , const DTDElementDecl::ModelTypes type 00059 , MemoryManager* const manager) : 00060 XMLElementDecl(manager) 00061 , fModelType(type) 00062 , fAttDefs(0) 00063 , fAttList(0) 00064 , fContentSpec(0) 00065 , fContentModel(0) 00066 , fFormattedModel(0) 00067 { 00068 setElementName(elemRawName, uriId); 00069 } 00070 00071 DTDElementDecl::DTDElementDecl( QName* const elementName 00072 , const DTDElementDecl::ModelTypes type 00073 , MemoryManager* const manager) : 00074 XMLElementDecl(manager) 00075 , fModelType(type) 00076 , fAttDefs(0) 00077 , fAttList(0) 00078 , fContentSpec(0) 00079 , fContentModel(0) 00080 , fFormattedModel(0) 00081 { 00082 setElementName(elementName); 00083 } 00084 00085 DTDElementDecl::~DTDElementDecl() 00086 { 00087 delete fAttDefs; 00088 delete fAttList; 00089 delete fContentSpec; 00090 delete fContentModel; 00091 getMemoryManager()->deallocate(fFormattedModel);//delete [] fFormattedModel; 00092 } 00093 00094 00095 00096 // --------------------------------------------------------------------------- 00097 // The virtual element decl interface 00098 // --------------------------------------------------------------------------- 00099 XMLAttDefList& DTDElementDecl::getAttDefList() const 00100 { 00101 if (!fAttList) 00102 { 00103 // If the att def list is not made yet, then fault it in too 00104 if (!fAttDefs) 00105 faultInAttDefList(); 00106 00107 ((DTDElementDecl*)this)->fAttList = new (getMemoryManager()) DTDAttDefList(fAttDefs,getMemoryManager()); 00108 } 00109 00110 return *fAttList; 00111 } 00112 00113 00114 XMLElementDecl::CharDataOpts DTDElementDecl::getCharDataOpts() const 00115 { 00116 XMLElementDecl::CharDataOpts retVal; 00117 switch(fModelType) 00118 { 00119 case Children : 00120 retVal = XMLElementDecl::SpacesOk; 00121 break; 00122 00123 case Empty : 00124 retVal = XMLElementDecl::NoCharData; 00125 break; 00126 00127 default : 00128 retVal = XMLElementDecl::AllCharData; 00129 break; 00130 } 00131 return retVal; 00132 } 00133 00134 00135 bool DTDElementDecl::hasAttDefs() const 00136 { 00137 // If the collection hasn't been faulted in, then no att defs 00138 if (!fAttDefs) 00139 return false; 00140 00141 return !fAttDefs->isEmpty(); 00142 } 00143 00144 void 00145 DTDElementDecl::setContentSpec(ContentSpecNode* toAdopt) 00146 { 00147 delete fContentSpec; 00148 fContentSpec = toAdopt; 00149 00150 //reset Content Model 00151 setContentModel(0); 00152 00153 } 00154 00155 const XMLCh* 00156 DTDElementDecl::getFormattedContentModel() const 00157 { 00158 // 00159 // If its not already built, then call the protected virtual method 00160 // to allow the derived class to build it (since only it knows.) 00161 // Otherwise, just return the previously formatted methods. 00162 // 00163 // Since we are faulting this in, within a const getter, we have to 00164 // cast off the const-ness. 00165 // 00166 if (!fFormattedModel) 00167 ((DTDElementDecl*)this)->fFormattedModel = formatContentModel(); 00168 00169 return fFormattedModel; 00170 } 00171 00172 00173 // --------------------------------------------------------------------------- 00174 // DTDElementDecl: Getter methods 00175 // --------------------------------------------------------------------------- 00176 const DTDAttDef* DTDElementDecl::getAttDef(const XMLCh* const attName) const 00177 { 00178 // If no list, then return a null 00179 if (!fAttDefs) 00180 return 0; 00181 00182 return fAttDefs->get(attName); 00183 } 00184 00185 00186 DTDAttDef* DTDElementDecl::getAttDef(const XMLCh* const attName) 00187 { 00188 // If no list, then return a null 00189 if (!fAttDefs) 00190 return 0; 00191 00192 return fAttDefs->get(attName); 00193 } 00194 00195 00196 // --------------------------------------------------------------------------- 00197 // DTDElementDecl: Implementation of the protected virtual interface 00198 // --------------------------------------------------------------------------- 00199 void DTDElementDecl::addAttDef(DTDAttDef* const toAdd) 00200 { 00201 // Fault in the att list if required 00202 if (!fAttDefs) 00203 faultInAttDefList(); 00204 00205 // Tell this guy the element id of its parent (us) 00206 toAdd->setElemId(getId()); 00207 00208 fAttDefs->put((void*)(toAdd->getFullName()), toAdd); 00209 // update and/or create fAttList 00210 if(!fAttList) 00211 ((DTDElementDecl*)this)->fAttList = new (getMemoryManager()) DTDAttDefList(fAttDefs,getMemoryManager()); 00212 fAttList->addAttDef(toAdd); 00213 } 00214 00215 00216 // --------------------------------------------------------------------------- 00217 // DTDElementDecl: Private helper methods 00218 // --------------------------------------------------------------------------- 00219 XMLCh* DTDElementDecl::formatContentModel() const 00220 { 00221 XMLCh* newValue = 0; 00222 if (fModelType == Any) 00223 { 00224 newValue = XMLString::replicate(XMLUni::fgAnyString, getMemoryManager()); 00225 } 00226 else if (fModelType == Empty) 00227 { 00228 newValue = XMLString::replicate(XMLUni::fgEmptyString, getMemoryManager()); 00229 } 00230 else 00231 { 00232 // 00233 // Use a temp XML buffer to format into. Content models could be 00234 // pretty long, but very few will be longer than one K. The buffer 00235 // will expand to handle the more pathological ones. 00236 // 00237 XMLBuffer bufFmt(1023, getMemoryManager()); 00238 getContentSpec()->formatSpec(bufFmt); 00239 newValue = XMLString::replicate(bufFmt.getRawBuffer(), getMemoryManager()); 00240 } 00241 return newValue; 00242 } 00243 00244 XMLContentModel* DTDElementDecl::makeContentModel() 00245 { 00246 XMLContentModel* cmRet = 0; 00247 if (fModelType == Mixed_Simple) 00248 { 00249 // 00250 // Just create a mixel content model object. This type of 00251 // content model is optimized for mixed content validation. 00252 // 00253 cmRet = new (getMemoryManager()) MixedContentModel(true, this->getContentSpec(), false, getMemoryManager()); 00254 } 00255 else if (fModelType == Children) 00256 { 00257 // 00258 // This method will create an optimal model for the complexity 00259 // of the element's defined model. If its simple, it will create 00260 // a SimpleContentModel object. If its a simple list, it will 00261 // create a SimpleListContentModel object. If its complex, it 00262 // will create a DFAContentModel object. 00263 // 00264 cmRet = createChildModel(); 00265 } 00266 else 00267 { 00268 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_MustBeMixedOrChildren, getMemoryManager()); 00269 } 00270 return cmRet; 00271 } 00272 00273 00274 XMLContentModel* DTDElementDecl::createChildModel() 00275 { 00276 // Get the content spec node of the element 00277 ContentSpecNode* specNode = getContentSpec(); 00278 00279 if(!specNode) 00280 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, getMemoryManager()); 00281 00282 // 00283 // Do a sanity check that the node does not have a PCDATA id. Since, 00284 // if it was, it should have already gotten taken by the Mixed model. 00285 // 00286 if (specNode->getElement()) { 00287 if (specNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId) 00288 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_NoPCDATAHere, getMemoryManager()); 00289 } 00290 00291 // 00292 // According to the type of node, we will create the correct type of 00293 // content model. 00294 // 00295 if (specNode->getType() == ContentSpecNode::Leaf) 00296 { 00297 // Create a simple content model 00298 return new (getMemoryManager()) SimpleContentModel 00299 ( 00300 true 00301 , specNode->getElement() 00302 , 0 00303 , ContentSpecNode::Leaf 00304 , getMemoryManager() 00305 ); 00306 } 00307 else if ((specNode->getType() == ContentSpecNode::Choice) 00308 || (specNode->getType() == ContentSpecNode::Sequence)) 00309 { 00310 // 00311 // Lets see if both of the children are leafs. If so, then it has to 00312 // be a simple content model 00313 // 00314 if ((specNode->getFirst()->getType() == ContentSpecNode::Leaf) 00315 && (specNode->getSecond()->getType() == ContentSpecNode::Leaf)) 00316 { 00317 return new (getMemoryManager()) SimpleContentModel 00318 ( 00319 true 00320 , specNode->getFirst()->getElement() 00321 , specNode->getSecond()->getElement() 00322 , specNode->getType() 00323 , getMemoryManager() 00324 ); 00325 } 00326 } 00327 else if ((specNode->getType() == ContentSpecNode::OneOrMore) 00328 || (specNode->getType() == ContentSpecNode::ZeroOrMore) 00329 || (specNode->getType() == ContentSpecNode::ZeroOrOne)) 00330 { 00331 // 00332 // Its a repetition, so see if its one child is a leaf. If so its a 00333 // repetition of a single element, so we can do a simple content 00334 // model for that. 00335 // 00336 if (specNode->getFirst()->getType() == ContentSpecNode::Leaf) 00337 { 00338 return new (getMemoryManager()) SimpleContentModel 00339 ( 00340 true 00341 , specNode->getFirst()->getElement() 00342 , 0 00343 , specNode->getType() 00344 , getMemoryManager() 00345 ); 00346 } 00347 } 00348 else 00349 { 00350 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, getMemoryManager()); 00351 } 00352 00353 // Its not any simple type of content, so create a DFA based content model 00354 return new (getMemoryManager()) DFAContentModel 00355 ( 00356 true 00357 , this->getContentSpec() 00358 , getMemoryManager() 00359 ); 00360 } 00361 00362 00363 void DTDElementDecl::faultInAttDefList() const 00364 { 00365 // Use a hash modulus of 29 and tell it owns its elements 00366 ((DTDElementDecl*)this)->fAttDefs = new (getMemoryManager()) RefHashTableOf<DTDAttDef>(29, true, getMemoryManager()); 00367 } 00368 00369 /*** 00370 * Support for Serialization/De-serialization 00371 ***/ 00372 00373 IMPL_XSERIALIZABLE_TOCREATE(DTDElementDecl) 00374 00375 void DTDElementDecl::serialize(XSerializeEngine& serEng) 00376 { 00377 00378 XMLElementDecl::serialize(serEng); 00379 00380 if (serEng.isStoring()) 00381 { 00382 serEng<<(int) fModelType; 00383 00384 /*** 00385 * 00386 * Serialize RefHashTableOf<DTDAttDef> 00387 * 00388 ***/ 00389 XTemplateSerializer::storeObject(fAttDefs, serEng); 00390 00391 serEng<<fAttList; 00392 serEng<<fContentSpec; 00393 00394 /*** 00395 * don't serialize 00396 * 00397 * XMLContentModel* fContentModel; 00398 * XMLCh* fFormattedModel; 00399 * 00400 ***/ 00401 00402 } 00403 else 00404 { 00405 int i; 00406 serEng>>i; 00407 fModelType=(ModelTypes)i; 00408 00409 /*** 00410 * 00411 * Deserialize RefHashTableOf<DTDAttDef> 00412 * 00413 ***/ 00414 XTemplateSerializer::loadObject(&fAttDefs, 29, true, serEng); 00415 00416 serEng>>fAttList; 00417 serEng>>fContentSpec; 00418 00419 /*** 00420 * don't deserialize 00421 * 00422 * XMLContentModel* fContentModel; 00423 * XMLCh* fFormattedModel; 00424 * 00425 ***/ 00426 fContentModel = 0; 00427 fFormattedModel = 0; 00428 } 00429 00430 } 00431 00432 XMLElementDecl::objectType DTDElementDecl::getObjectType() const 00433 { 00434 return DTD; 00435 } 00436 00437 XERCES_CPP_NAMESPACE_END