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: ContentSpecNode.cpp 933155 2010-04-12 09:07:02Z amassari $ 00020 */ 00021 00022 00023 // --------------------------------------------------------------------------- 00024 // Includes 00025 // --------------------------------------------------------------------------- 00026 #include <xercesc/framework/XMLBuffer.hpp> 00027 #include <xercesc/validators/common/ContentSpecNode.hpp> 00028 #include <xercesc/validators/schema/SchemaSymbols.hpp> 00029 00030 XERCES_CPP_NAMESPACE_BEGIN 00031 00032 // --------------------------------------------------------------------------- 00033 // ContentSpecNode: Copy Constructor 00034 // 00035 // Note: this copy constructor has dependency on various get*() methods 00036 // and shall be placed after those method's declaration. 00037 // aka inline function compilation error on AIX 4.2, xlC 3 r ev.1 00038 // --------------------------------------------------------------------------- 00039 00040 ContentSpecNode::ContentSpecNode(const ContentSpecNode& toCopy) : 00041 XSerializable(toCopy) 00042 , XMemory(toCopy) 00043 , fMemoryManager(toCopy.fMemoryManager) 00044 , fElement(0) 00045 , fElementDecl(toCopy.fElementDecl) 00046 , fFirst(0) 00047 , fSecond(0) 00048 , fType(toCopy.fType) 00049 , fAdoptFirst(true) 00050 , fAdoptSecond(true) 00051 , fMinOccurs(toCopy.fMinOccurs) 00052 , fMaxOccurs(toCopy.fMaxOccurs) 00053 { 00054 const QName* tempElement = toCopy.getElement(); 00055 if (tempElement) 00056 fElement = new (fMemoryManager) QName(*tempElement); 00057 00058 const ContentSpecNode *tmp = toCopy.getFirst(); 00059 if (tmp) 00060 fFirst = new (fMemoryManager) ContentSpecNode(*tmp); 00061 00062 tmp = toCopy.getSecond(); 00063 if (tmp) 00064 fSecond = new (fMemoryManager) ContentSpecNode(*tmp); 00065 } 00066 00067 // --------------------------------------------------------------------------- 00068 // Local methods 00069 // --------------------------------------------------------------------------- 00070 static void formatNode( const ContentSpecNode* const curNode 00071 , const ContentSpecNode::NodeTypes parentType 00072 , XMLBuffer& bufToFill) 00073 { 00074 if (!curNode) 00075 return; 00076 00077 const ContentSpecNode* first = curNode->getFirst(); 00078 const ContentSpecNode* second = curNode->getSecond(); 00079 const ContentSpecNode::NodeTypes curType = curNode->getType(); 00080 00081 // Get the type of the first node 00082 const ContentSpecNode::NodeTypes firstType = first ? 00083 first->getType() : 00084 ContentSpecNode::Leaf; 00085 00086 // Calculate the parens flag for the rep nodes 00087 bool doRepParens = false; 00088 if (((firstType != ContentSpecNode::Leaf) 00089 && (parentType != ContentSpecNode::UnknownType)) 00090 || ((firstType == ContentSpecNode::Leaf) 00091 && (parentType == ContentSpecNode::UnknownType))) 00092 { 00093 doRepParens = true; 00094 } 00095 00096 // Now handle our type 00097 switch(curType & 0x0f) 00098 { 00099 case ContentSpecNode::Leaf : 00100 if (curNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId) 00101 bufToFill.append(XMLElementDecl::fgPCDataElemName); 00102 else 00103 { 00104 bufToFill.append(curNode->getElement()->getRawName()); 00105 // show the + and * modifiers also when we have a non-infinite number of repetitions 00106 if(curNode->getMinOccurs()==0 && (curNode->getMaxOccurs()==-1 || curNode->getMaxOccurs()>1)) 00107 bufToFill.append(chAsterisk); 00108 else if(curNode->getMinOccurs()==0 && curNode->getMaxOccurs()==1) 00109 bufToFill.append(chQuestion); 00110 else if(curNode->getMinOccurs()==1 && (curNode->getMaxOccurs()==-1 || curNode->getMaxOccurs()>1)) 00111 bufToFill.append(chPlus); 00112 } 00113 break; 00114 00115 case ContentSpecNode::ZeroOrOne : 00116 if (doRepParens) 00117 bufToFill.append(chOpenParen); 00118 formatNode(first, curType, bufToFill); 00119 if (doRepParens) 00120 bufToFill.append(chCloseParen); 00121 bufToFill.append(chQuestion); 00122 break; 00123 00124 case ContentSpecNode::ZeroOrMore : 00125 if (doRepParens) 00126 bufToFill.append(chOpenParen); 00127 formatNode(first, curType, bufToFill); 00128 if (doRepParens) 00129 bufToFill.append(chCloseParen); 00130 bufToFill.append(chAsterisk); 00131 break; 00132 00133 case ContentSpecNode::OneOrMore : 00134 if (doRepParens) 00135 bufToFill.append(chOpenParen); 00136 formatNode(first, curType, bufToFill); 00137 if (doRepParens) 00138 bufToFill.append(chCloseParen); 00139 bufToFill.append(chPlus); 00140 break; 00141 00142 case ContentSpecNode::Choice : 00143 if ((parentType & 0x0f) != (curType & 0x0f)) 00144 bufToFill.append(chOpenParen); 00145 formatNode(first, curType, bufToFill); 00146 if(second!=NULL) 00147 { 00148 bufToFill.append(chPipe); 00149 formatNode(second, curType, bufToFill); 00150 } 00151 if ((parentType & 0x0f) != (curType & 0x0f)) 00152 bufToFill.append(chCloseParen); 00153 break; 00154 00155 case ContentSpecNode::Sequence : 00156 if ((parentType & 0x0f) != (curType & 0x0f)) 00157 bufToFill.append(chOpenParen); 00158 formatNode(first, curType, bufToFill); 00159 if(second!=NULL) 00160 { 00161 bufToFill.append(chComma); 00162 formatNode(second, curType, bufToFill); 00163 } 00164 if ((parentType & 0x0f) != (curType & 0x0f)) 00165 bufToFill.append(chCloseParen); 00166 break; 00167 00168 case ContentSpecNode::All : 00169 if ((parentType & 0x0f) != (curType & 0x0f)) 00170 { 00171 bufToFill.append(chLatin_A); 00172 bufToFill.append(chLatin_l); 00173 bufToFill.append(chLatin_l); 00174 bufToFill.append(chOpenParen); 00175 } 00176 formatNode(first, curType, bufToFill); 00177 bufToFill.append(chComma); 00178 formatNode(second, curType, bufToFill); 00179 if ((parentType & 0x0f) != (curType & 0x0f)) 00180 bufToFill.append(chCloseParen); 00181 break; 00182 } 00183 } 00184 00185 00186 // --------------------------------------------------------------------------- 00187 // ContentSpecNode: Miscellaneous 00188 // --------------------------------------------------------------------------- 00189 void ContentSpecNode::formatSpec(XMLBuffer& bufToFill) const 00190 { 00191 // Clean out the buffer first 00192 bufToFill.reset(); 00193 00194 if (fType == ContentSpecNode::Leaf) 00195 bufToFill.append(chOpenParen); 00196 formatNode 00197 ( 00198 this 00199 , UnknownType 00200 , bufToFill 00201 ); 00202 if (fType == ContentSpecNode::Leaf) 00203 bufToFill.append(chCloseParen); 00204 } 00205 00206 int ContentSpecNode::getMinTotalRange() const { 00207 00208 int min = fMinOccurs; 00209 00210 if ((fType & 0x0f) == ContentSpecNode::Sequence 00211 || fType == ContentSpecNode::All 00212 || (fType & 0x0f) == ContentSpecNode::Choice) { 00213 00214 int minFirst = fFirst->getMinTotalRange(); 00215 00216 if (fSecond) { 00217 00218 int minSecond = fSecond->getMinTotalRange(); 00219 00220 if ((fType & 0x0f) == ContentSpecNode::Choice) { 00221 min = min * ((minFirst < minSecond)? minFirst : minSecond); 00222 } 00223 else { 00224 min = min * (minFirst + minSecond); 00225 } 00226 } 00227 else 00228 min = min * minFirst; 00229 } 00230 00231 return min; 00232 } 00233 00234 int ContentSpecNode::getMaxTotalRange() const { 00235 00236 int max = fMaxOccurs; 00237 00238 if (max == SchemaSymbols::XSD_UNBOUNDED) { 00239 return SchemaSymbols::XSD_UNBOUNDED; 00240 } 00241 00242 if ((fType & 0x0f) == ContentSpecNode::Sequence 00243 || fType == ContentSpecNode::All 00244 || (fType & 0x0f) == ContentSpecNode::Choice) { 00245 00246 int maxFirst = fFirst->getMaxTotalRange(); 00247 00248 if (maxFirst == SchemaSymbols::XSD_UNBOUNDED) { 00249 return SchemaSymbols::XSD_UNBOUNDED; 00250 } 00251 00252 if (fSecond) { 00253 00254 int maxSecond = fSecond->getMaxTotalRange(); 00255 00256 if (maxSecond == SchemaSymbols::XSD_UNBOUNDED) { 00257 return SchemaSymbols::XSD_UNBOUNDED; 00258 } 00259 else { 00260 00261 if ((fType & 0x0f) == ContentSpecNode::Choice) { 00262 max = max * (maxFirst > maxSecond) ? maxFirst : maxSecond; 00263 } 00264 else { 00265 max = max * (maxFirst + maxSecond); 00266 } 00267 } 00268 } 00269 else { 00270 max = max * maxFirst; 00271 } 00272 } 00273 00274 return max; 00275 } 00276 00277 /*** 00278 * Support for Serialization/De-serialization 00279 ***/ 00280 00281 IMPL_XSERIALIZABLE_TOCREATE(ContentSpecNode) 00282 00283 void ContentSpecNode::serialize(XSerializeEngine& serEng) 00284 { 00285 /*** 00286 * Since fElement, fFirst, fSecond are NOT created by the default 00287 * constructor, we need to create them dynamically. 00288 ***/ 00289 00290 if (serEng.isStoring()) 00291 { 00292 serEng<<fElement; 00293 XMLElementDecl::storeElementDecl(serEng, fElementDecl); 00294 serEng<<fFirst; 00295 serEng<<fSecond; 00296 00297 serEng<<(int)fType; 00298 serEng<<fAdoptFirst; 00299 serEng<<fAdoptSecond; 00300 serEng<<fMinOccurs; 00301 serEng<<fMaxOccurs; 00302 } 00303 else 00304 { 00305 serEng>>fElement; 00306 fElementDecl = XMLElementDecl::loadElementDecl(serEng); 00307 serEng>>fFirst; 00308 serEng>>fSecond; 00309 00310 int type; 00311 serEng>>type; 00312 fType = (NodeTypes)type; 00313 00314 serEng>>fAdoptFirst; 00315 serEng>>fAdoptSecond; 00316 serEng>>fMinOccurs; 00317 serEng>>fMaxOccurs; 00318 } 00319 00320 } 00321 00322 XERCES_CPP_NAMESPACE_END 00323