GME  13
SimpleContentModel.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: SimpleContentModel.cpp 799211 2009-07-30 09:06:43Z amassari $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #include <xercesc/util/RuntimeException.hpp>
00027 #include <xercesc/framework/XMLValidator.hpp>
00028 #include <xercesc/validators/common/SimpleContentModel.hpp>
00029 #include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
00030 #include <xercesc/validators/schema/XercesElementWildcard.hpp>
00031 
00032 XERCES_CPP_NAMESPACE_BEGIN
00033 
00034 // ---------------------------------------------------------------------------
00035 //  SimpleContentModel: Implementation of the ContentModel virtual interface
00036 // ---------------------------------------------------------------------------
00037 //
00038 //  This method is called to validate our content. For this one, its just a
00039 //  pretty simple 'bull your way through it' test according to what kind of
00040 //  operation it is for.
00041 //
00042 bool
00043 SimpleContentModel::validateContent(QName** const       children
00044                                   , XMLSize_t           childCount
00045                                   , unsigned int
00046                                   , XMLSize_t*          indexFailingChild
00047                                   , MemoryManager*    const) const
00048 {
00049     //
00050     //  According to the type of operation, we do the correct type of
00051     //  content check.
00052     //
00053     XMLSize_t index;
00054     switch(fOp & 0x0f)
00055     {
00056         case ContentSpecNode::Leaf :
00057             //
00058             //  There can only be one child and it has to be of the
00059             //  element type we stored.
00060             //
00061             if (!childCount)
00062             {
00063                 *indexFailingChild=0;
00064                 return false;
00065             }
00066 
00067             // If the 0th child is not the right kind, report an error at 0
00068             if (fDTD) {
00069                 if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName())) {
00070                     *indexFailingChild=0;
00071                     return false;
00072                 }
00073             }
00074             else {
00075                 if ((children[0]->getURI() != fFirstChild->getURI()) ||
00076                     !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) {
00077                     *indexFailingChild=0;
00078                     return false;
00079                 }
00080             }
00081 
00082             if (childCount > 1)
00083             {
00084                 *indexFailingChild=1;
00085                 return false;
00086             }
00087             break;
00088 
00089         case ContentSpecNode::ZeroOrOne :
00090             //
00091             //  If the child count is greater than one, then obviously
00092             //  bad. Otherwise, if its one, then the one child must be
00093             //  of the type we stored.
00094             //
00095             if (childCount == 1) {
00096                 if (fDTD) {
00097                     if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName())) {
00098                         *indexFailingChild=0;
00099                         return false;
00100                     }
00101                 }
00102                 else {
00103                     if ((children[0]->getURI() != fFirstChild->getURI()) ||
00104                         (!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))) {
00105                         *indexFailingChild=0;
00106                         return false;
00107                     }
00108                 }
00109             }
00110 
00111             if (childCount > 1)
00112             {
00113                 *indexFailingChild=1;
00114                 return false;
00115             }
00116             break;
00117 
00118         case ContentSpecNode::ZeroOrMore :
00119             //
00120             //  If the child count is zero, that's fine. If its more than
00121             //  zero, then make sure that all children are of the element
00122             //  type that we stored.
00123             //
00124             if (childCount > 0)
00125             {
00126                 if (fDTD) {
00127                     for (index = 0; index < childCount; index++) {
00128                         if (!XMLString::equals(children[index]->getRawName(), fFirstChild->getRawName())) {
00129                             *indexFailingChild=index;
00130                             return false;
00131                         }
00132                     }
00133                 }
00134                 else {
00135                     for (index = 0; index < childCount; index++) {
00136                         if ((children[index]->getURI() != fFirstChild->getURI()) ||
00137                             !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart())) {
00138                             *indexFailingChild=index;
00139                             return false;
00140                         }
00141                     }
00142                 }
00143             }
00144             break;
00145 
00146         case ContentSpecNode::OneOrMore :
00147             //
00148             //  If the child count is zero, that's an error. If its more
00149             //  than zero, then make sure that all children are of the
00150             //  element type that we stored.
00151             //
00152             if (childCount == 0)
00153             {
00154                 *indexFailingChild=0;
00155                 return false;
00156             }
00157 
00158             if (fDTD) {
00159                 for (index = 0; index < childCount; index++) {
00160                     if (!XMLString::equals(children[index]->getRawName(), fFirstChild->getRawName())) {
00161                         *indexFailingChild=index;
00162                         return false;
00163                     }
00164                 }
00165             }
00166             else {
00167                 for (index = 0; index < childCount; index++) {
00168                     if ((children[index]->getURI() != fFirstChild->getURI()) ||
00169                         !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart())) {
00170                         *indexFailingChild=index;
00171                         return false;
00172                     }
00173                 }
00174             }
00175             break;
00176 
00177         case ContentSpecNode::Choice :
00178             //
00179             //  There can only be one child, and it must be one of the
00180             //  two types we stored.
00181             //
00182             if (!childCount)
00183             {
00184                 *indexFailingChild=0;
00185                 return false;
00186             }
00187 
00188             if (fDTD) {
00189                 if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName()) &&
00190                     !XMLString::equals(children[0]->getRawName(), fSecondChild->getRawName())) {
00191                     *indexFailingChild=0;
00192                     return false;
00193                 }
00194             }
00195             else {
00196                 if (((children[0]->getURI() != fFirstChild->getURI()) ||
00197                      !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) &&
00198                     ((children[0]->getURI() != fSecondChild->getURI()) ||
00199                      !XMLString::equals(children[0]->getLocalPart(), fSecondChild->getLocalPart()))) {
00200                      *indexFailingChild=0;
00201                      return false;
00202                 }
00203             }
00204 
00205             if (childCount > 1)
00206             {
00207                 *indexFailingChild=1;
00208                 return false;
00209             }
00210             break;
00211 
00212         case ContentSpecNode::Sequence :
00213             //
00214             //  There must be two children and they must be the two values
00215             //  we stored, in the stored order. So first check the obvious
00216             //  problem of an empty content, which would never be valid
00217             //  in this content mode.
00218             //
00219             if (!childCount)
00220             {
00221                 *indexFailingChild=0;
00222                 return false;
00223             }
00224 
00225             // test first child
00226             if (fDTD) {
00227                 if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName())) {
00228                     *indexFailingChild=0;
00229                     return false;
00230                 }
00231             }
00232             else {
00233                 if ((children[0]->getURI() != fFirstChild->getURI()) ||
00234                     !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) {
00235                     *indexFailingChild=0;
00236                     return false;
00237                 }
00238             }
00239             // test second child, if present
00240             if( childCount == 1)
00241             {
00242                 // missing second child
00243                 *indexFailingChild=1;
00244                 return false;
00245             }
00246             else
00247             {
00248                 if (fDTD) {
00249                     if (!XMLString::equals(children[1]->getRawName(), fSecondChild->getRawName())) {
00250                         *indexFailingChild=1;
00251                         return false;
00252                     }
00253                 }
00254                 else {
00255                     if ((children[1]->getURI() != fSecondChild->getURI()) ||
00256                         !XMLString::equals(children[1]->getLocalPart(), fSecondChild->getLocalPart())) {
00257                         *indexFailingChild=1;
00258                         return false;
00259                     }
00260                 }
00261 
00262                 if (childCount > 2) {
00263                     *indexFailingChild=2;
00264                     return false;
00265                 }
00266             }
00267             break;
00268 
00269         default :
00270             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
00271             break;
00272     }
00273     return true;
00274 }
00275 
00276 bool SimpleContentModel::validateContentSpecial(QName** const         children
00277                                             , XMLSize_t               childCount
00278                                             , unsigned int
00279                                             , GrammarResolver*  const pGrammarResolver
00280                                             , XMLStringPool*    const pStringPool
00281                                             , XMLSize_t*              indexFailingChild
00282                                             , MemoryManager*    const) const
00283 {
00284 
00285     SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
00286 
00287     //
00288     //  According to the type of operation, we do the correct type of
00289     //  content check.
00290     //
00291     unsigned int index;
00292     switch(fOp & 0x0f)
00293     {
00294         case ContentSpecNode::Leaf :
00295             //
00296             //  There can only be one child and it has to be of the
00297             //  element type we stored.
00298             //
00299             if (!childCount)
00300             {
00301                 *indexFailingChild=0;
00302                 return false;
00303             }
00304 
00305             if ((children[0]->getURI() != fFirstChild->getURI()) ||
00306                 !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))
00307             {
00308                 if (!comparator.isEquivalentTo(children[0], fFirstChild))
00309                 {
00310                     *indexFailingChild=0;
00311                     return false;
00312                 }
00313             }
00314 
00315             if (childCount > 1)
00316             {
00317                 *indexFailingChild=1;
00318                 return false;
00319             }
00320             break;
00321 
00322         case ContentSpecNode::ZeroOrOne :
00323             //
00324             //  If the child count is greater than one, then obviously
00325             //  bad. Otherwise, if its one, then the one child must be
00326             //  of the type we stored.
00327             //
00328             if ((childCount == 1) &&
00329                ((children[0]->getURI() != fFirstChild->getURI()) ||
00330                 !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())))
00331             {
00332                 if(!comparator.isEquivalentTo(children[0], fFirstChild))
00333                 {
00334                     *indexFailingChild=0;
00335                     return false;
00336                 }
00337             }
00338 
00339             if (childCount > 1)
00340             {
00341                 *indexFailingChild=1;
00342                 return false;
00343             }
00344             break;
00345 
00346         case ContentSpecNode::ZeroOrMore :
00347             //
00348             //  If the child count is zero, that's fine. If its more than
00349             //  zero, then make sure that all children are of the element
00350             //  type that we stored.
00351             //
00352             if (childCount > 0)
00353             {
00354                 for (index = 0; index < childCount; index++)
00355                 {
00356                     if ((children[index]->getURI() != fFirstChild->getURI()) ||
00357                         !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart()))
00358                     {
00359                         if (!comparator.isEquivalentTo(children[index], fFirstChild))
00360                         {
00361                             *indexFailingChild=index;
00362                             return false;
00363                         }
00364                     }
00365                 }
00366             }
00367             break;
00368 
00369         case ContentSpecNode::OneOrMore :
00370             //
00371             //  If the child count is zero, that's an error. If its more
00372             //  than zero, then make sure that all children are of the
00373             //  element type that we stored.
00374             //
00375             if (childCount == 0)
00376             {
00377                 *indexFailingChild=0;
00378                 return false;
00379             }
00380 
00381             for (index = 0; index < childCount; index++)
00382             {
00383                 if ((children[index]->getURI() != fFirstChild->getURI()) ||
00384                     !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart()))
00385                 {
00386                     if (!comparator.isEquivalentTo(children[index], fFirstChild))
00387                     {
00388                         *indexFailingChild=index;
00389                         return false;
00390                     }
00391                 }
00392             }
00393             break;
00394 
00395         case ContentSpecNode::Choice :
00396             //
00397             //  There can only be one child, and it must be one of the
00398             //  two types we stored.
00399             //
00400             if (!childCount)
00401             {
00402                 *indexFailingChild=0;
00403                 return false;
00404             }
00405 
00406             if (((children[0]->getURI() != fFirstChild->getURI()) ||
00407                  !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) &&
00408                 ((children[0]->getURI() != fSecondChild->getURI()) ||
00409                  !XMLString::equals(children[0]->getLocalPart(), fSecondChild->getLocalPart())))
00410             {
00411 
00412                  if (!comparator.isEquivalentTo(children[0], fFirstChild) &&
00413                      !comparator.isEquivalentTo(children[0], fSecondChild) )
00414                  {
00415                      *indexFailingChild=0;
00416                      return false;
00417                  }
00418             }
00419 
00420             if (childCount > 1)
00421             {
00422                 *indexFailingChild=1;
00423                 return false;
00424             }
00425             break;
00426 
00427         case ContentSpecNode::Sequence :
00428             //
00429             //  There must be two children and they must be the two values
00430             //  we stored, in the stored order. So first check the obvious
00431             //  problem of an empty content, which would never be valid
00432             //  in this content mode.
00433             //
00434             if (!childCount)
00435             {
00436                 *indexFailingChild=0;
00437                 return false;
00438             }
00439 
00440             // test first child
00441             if ((children[0]->getURI() != fFirstChild->getURI()) ||
00442                 !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))
00443             {
00444                 if(!comparator.isEquivalentTo(children[0], fFirstChild))
00445                 {
00446                     *indexFailingChild=0;
00447                     return false;
00448                 }
00449             }
00450             // test second child, if present
00451             if( childCount == 1)
00452             {
00453                 // missing second child
00454                 *indexFailingChild=1;
00455                 return false;
00456             }
00457             else
00458             {
00459                 if ((children[1]->getURI() != fSecondChild->getURI()) ||
00460                     !XMLString::equals(children[1]->getLocalPart(), fSecondChild->getLocalPart()))
00461                 {
00462                     if (!comparator.isEquivalentTo(children[1], fSecondChild))
00463                     {
00464                         *indexFailingChild=1;
00465                         return false;
00466                     }
00467                 }
00468 
00469                 if (childCount > 2) {
00470                     *indexFailingChild=2;
00471                     return false;
00472                 }
00473 
00474             }
00475             break;
00476 
00477         default :
00478             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMSpecType, fMemoryManager);
00479             break;
00480     }
00481     return true;
00482 }
00483 
00484 ContentLeafNameTypeVector* SimpleContentModel::getContentLeafNameTypeVector() const
00485 {
00486     return 0;
00487 }
00488 
00489 void SimpleContentModel::checkUniqueParticleAttribution
00490     (
00491         SchemaGrammar*    const pGrammar
00492       , GrammarResolver*  const pGrammarResolver
00493       , XMLStringPool*    const pStringPool
00494       , XMLValidator*     const pValidator
00495       , unsigned int*     const pContentSpecOrgURI
00496       , const XMLCh*            pComplexTypeName /*= 0*/
00497     )
00498 {
00499     // rename back
00500     unsigned int orgURIIndex = 0;
00501 
00502     orgURIIndex = fFirstChild->getURI();
00503     if ((orgURIIndex != XMLContentModel::gEOCFakeId) &&
00504         (orgURIIndex != XMLElementDecl::fgInvalidElemId) &&
00505         (orgURIIndex != XMLElementDecl::fgPCDataElemId))
00506         fFirstChild->setURI(pContentSpecOrgURI[orgURIIndex]);
00507 
00508     orgURIIndex = fSecondChild->getURI();
00509     if ((orgURIIndex != XMLContentModel::gEOCFakeId) &&
00510         (orgURIIndex != XMLElementDecl::fgInvalidElemId) &&
00511         (orgURIIndex != XMLElementDecl::fgPCDataElemId))
00512         fSecondChild->setURI(pContentSpecOrgURI[orgURIIndex]);
00513 
00514     // only possible violation is when it's a choice
00515     if ((fOp & 0x0f) == ContentSpecNode::Choice) {
00516 
00517         SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
00518 
00519         if (XercesElementWildcard::conflict(pGrammar,
00520                                             ContentSpecNode::Leaf,
00521                                             fFirstChild,
00522                                             ContentSpecNode::Leaf,
00523                                             fSecondChild,
00524                                             &comparator))
00525 
00526             pValidator->emitError(XMLValid::UniqueParticleAttributionFail,
00527                                   pComplexTypeName,
00528                                   fFirstChild->getRawName(),
00529                                   fSecondChild->getRawName());
00530     }
00531 }
00532 
00533 XERCES_CPP_NAMESPACE_END
00534