SimpleContentModel.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:20k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Log: SimpleContentModel.cpp,v $
  58.  * Revision 1.4  2002/11/04 14:54:58  tng
  59.  * C++ Namespace Support.
  60.  *
  61.  * Revision 1.3  2002/09/24 19:48:39  tng
  62.  * Performance: use XMLString::equals instead of XMLString::compareString
  63.  *
  64.  * Revision 1.2  2002/02/25 21:18:53  tng
  65.  * Schema Fix: Ensure no invalid uri index for UPA checking.
  66.  *
  67.  * Revision 1.1.1.1  2002/02/01 22:22:39  peiyongz
  68.  * sane_include
  69.  *
  70.  * Revision 1.11  2001/11/28 16:46:20  tng
  71.  * Schema fix: Check for invalid URI index first.
  72.  *
  73.  * Revision 1.10  2001/11/21 14:30:13  knoaman
  74.  * Fix for UPA checking.
  75.  *
  76.  * Revision 1.9  2001/08/21 16:06:11  tng
  77.  * Schema: Unique Particle Attribution Constraint Checking.
  78.  *
  79.  * Revision 1.8  2001/05/11 13:27:19  tng
  80.  * Copyright update.
  81.  *
  82.  * Revision 1.7  2001/05/03 21:02:32  tng
  83.  * Schema: Add SubstitutionGroupComparator and update exception messages.  By Pei Yong Zhang.
  84.  *
  85.  * Revision 1.6  2001/04/19 18:17:33  tng
  86.  * Schema: SchemaValidator update, and use QName in Content Model
  87.  *
  88.  * Revision 1.5  2001/03/21 21:56:29  tng
  89.  * Schema: Add Schema Grammar, Schema Validator, and split the DTDValidator into DTDValidator, DTDScanner, and DTDGrammar.
  90.  *
  91.  * Revision 1.4  2001/03/21 19:30:00  tng
  92.  * Schema: Content Model Updates, by Pei Yong Zhang.
  93.  *
  94.  * Revision 1.3  2001/02/27 14:48:57  tng
  95.  * Schema: Add CMAny and ContentLeafNameTypeVector, by Pei Yong Zhang
  96.  *
  97.  * Revision 1.2  2001/02/16 14:58:57  tng
  98.  * Schema: Update Makefile, configure files, project files, and include path in
  99.  * certain cpp files because of the move of the common Content Model files.  By Pei Yong Zhang.
  100.  *
  101.  * Revision 1.1  2001/02/16 14:17:29  tng
  102.  * Schema: Move the common Content Model files that are shared by DTD
  103.  * and schema from 'DTD' folder to 'common' folder.  By Pei Yong Zhang.
  104.  *
  105.  * Revision 1.4  2000/03/03 22:33:00  roddey
  106.  * Fixed a bug in SimpleContentModel that allowed an <a/> to be taken
  107.  * as valid for a content model of (a,b).
  108.  *
  109.  * Revision 1.3  2000/03/02 19:55:40  roddey
  110.  * This checkin includes many changes done while waiting for the
  111.  * 1.1.0 code to be finished. I can't list them all here, but a list is
  112.  * available elsewhere.
  113.  *
  114.  * Revision 1.2  2000/02/09 21:42:39  abagchi
  115.  * Copyright swatswat
  116.  *
  117.  * Revision 1.1.1.1  1999/11/09 01:03:46  twl
  118.  * Initial checkin
  119.  *
  120.  * Revision 1.2  1999/11/08 20:45:44  rahul
  121.  * Swat for adding in Product name and CVS comment log variable.
  122.  *
  123.  */
  124. // ---------------------------------------------------------------------------
  125. //  Includes
  126. // ---------------------------------------------------------------------------
  127. #include <xercesc/util/RuntimeException.hpp>
  128. #include <xercesc/framework/XMLValidator.hpp>
  129. #include <xercesc/validators/common/SimpleContentModel.hpp>
  130. #include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
  131. #include <xercesc/validators/schema/XercesElementWildcard.hpp>
  132. XERCES_CPP_NAMESPACE_BEGIN
  133. // ---------------------------------------------------------------------------
  134. //  SimpleContentModel: Implementation of the ContentModel virtual interface
  135. // ---------------------------------------------------------------------------
  136. //
  137. //  This method is called to validate our content. For this one, its just a
  138. //  pretty simple 'bull your way through it' test according to what kind of
  139. //  operation it is for.
  140. //
  141. int
  142. SimpleContentModel::validateContent(QName** const       children
  143.                                   , const unsigned int  childCount
  144.                                   , const unsigned int  emptyNamespaceId) const
  145. {
  146.     //
  147.     //  According to the type of operation, we do the correct type of
  148.     //  content check.
  149.     //
  150.     unsigned int index;
  151.     switch(fOp)
  152.     {
  153.         case ContentSpecNode::Leaf :
  154.             //
  155.             //  There can only be one child and it has to be of the
  156.             //  element type we stored.
  157.             //
  158.             if (!childCount)
  159.                 return 0;
  160.             // If the 0th child is not the right kind, report an error at 0
  161.             if (fDTD) {
  162.                 if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName())) {
  163.                     return 0;
  164.                 }
  165.             }
  166.             else {
  167.                 if ((children[0]->getURI() != fFirstChild->getURI()) ||
  168.                     !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) {
  169.                     return 0;
  170.                 }
  171.             }
  172.             if (childCount > 1)
  173.                 return 1;
  174.             break;
  175.         case ContentSpecNode::ZeroOrOne :
  176.             //
  177.             //  If the child count is greater than one, then obviously
  178.             //  bad. Otherwise, if its one, then the one child must be
  179.             //  of the type we stored.
  180.             //
  181.             if (childCount == 1) {
  182.                 if (fDTD) {
  183.                     if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName())) {
  184.                             return 0;
  185.                     }
  186.                 }
  187.                 else {
  188.                     if ((children[0]->getURI() != fFirstChild->getURI()) ||
  189.                         (!XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))) {
  190.                         return 0;
  191.                     }
  192.                 }
  193.             }
  194.             if (childCount > 1)
  195.                 return 1;
  196.             break;
  197.         case ContentSpecNode::ZeroOrMore :
  198.             //
  199.             //  If the child count is zero, that's fine. If its more than
  200.             //  zero, then make sure that all children are of the element
  201.             //  type that we stored.
  202.             //
  203.             if (childCount > 0)
  204.             {
  205.                 if (fDTD) {
  206.                     for (index = 0; index < childCount; index++) {
  207.                         if (!XMLString::equals(children[index]->getRawName(), fFirstChild->getRawName())) {
  208.                             return index;
  209.                         }
  210.                     }
  211.                 }
  212.                 else {
  213.                     for (index = 0; index < childCount; index++) {
  214.                         if ((children[index]->getURI() != fFirstChild->getURI()) ||
  215.                             !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart())) {
  216.                             return index;
  217.                         }
  218.                     }
  219.                 }
  220.             }
  221.             break;
  222.         case ContentSpecNode::OneOrMore :
  223.             //
  224.             //  If the child count is zero, that's an error. If its more
  225.             //  than zero, then make sure that all children are of the
  226.             //  element type that we stored.
  227.             //
  228.             if (childCount == 0)
  229.                 return 0;
  230.             if (fDTD) {
  231.                 for (index = 0; index < childCount; index++) {
  232.                     if (!XMLString::equals(children[index]->getRawName(), fFirstChild->getRawName())) {
  233.                         return index;
  234.                     }
  235.                 }
  236.             }
  237.             else {
  238.                 for (index = 0; index < childCount; index++) {
  239.                     if ((children[index]->getURI() != fFirstChild->getURI()) ||
  240.                         !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart())) {
  241.                         return index;
  242.                     }
  243.                 }
  244.             }
  245.             break;
  246.         case ContentSpecNode::Choice :
  247.             //
  248.             //  There can only be one child, and it must be one of the
  249.             //  two types we stored.
  250.             //
  251.             if (!childCount)
  252.                 return 0;
  253.             if (fDTD) {
  254.                 if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName()) &&
  255.                     !XMLString::equals(children[0]->getRawName(), fSecondChild->getRawName())) {
  256.                     return 0;
  257.                 }
  258.             }
  259.             else {
  260.                 if (((children[0]->getURI() != fFirstChild->getURI()) ||
  261.                      !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) &&
  262.                     ((children[0]->getURI() != fSecondChild->getURI()) ||
  263.                      !XMLString::equals(children[0]->getLocalPart(), fSecondChild->getLocalPart()))) {
  264.                     return 0;
  265.                 }
  266.             }
  267.             if (childCount > 1)
  268.                 return 1;
  269.             break;
  270.         case ContentSpecNode::Sequence :
  271.             //
  272.             //  There must be two children and they must be the two values
  273.             //  we stored, in the stored order. So first check the obvious
  274.             //  problem of an empty content, which would never be valid
  275.             //  in this content mode.
  276.             //
  277.             if (!childCount)
  278.                 return 0;
  279.             if (childCount == 2) {
  280.                 if (fDTD) {
  281.                     if (!XMLString::equals(children[0]->getRawName(), fFirstChild->getRawName())) {
  282.                         return 0;
  283.                     }
  284.                     if (!XMLString::equals(children[1]->getRawName(), fSecondChild->getRawName())) {
  285.                         return 1;
  286.                     }
  287.                 }
  288.                 else {
  289.                     if ((children[0]->getURI() != fFirstChild->getURI()) ||
  290.                         !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) {
  291.                         return 0;
  292.                     }
  293.                     if ((children[1]->getURI() != fSecondChild->getURI()) ||
  294.                         !XMLString::equals(children[1]->getLocalPart(), fSecondChild->getLocalPart())) {
  295.                         return 1;
  296.                     }
  297.                 }
  298.             }
  299.             else {
  300.                 if (childCount > 2) {
  301.                     return 2;
  302.                 }
  303.                 return childCount;
  304.             }
  305.             break;
  306.         default :
  307.             ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMSpecType);
  308.             break;
  309.     }
  310.     return -1;
  311. }
  312. int SimpleContentModel::validateContentSpecial(QName** const          children
  313.                                             , const unsigned int      childCount
  314.                                             , const unsigned int      emptyNamespaceId
  315.                                             , GrammarResolver*  const pGrammarResolver
  316.                                             , XMLStringPool*    const pStringPool) const
  317. {
  318.     SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
  319.     //
  320.     //  According to the type of operation, we do the correct type of
  321.     //  content check.
  322.     //
  323.     unsigned int index;
  324.     switch(fOp)
  325.     {
  326.         case ContentSpecNode::Leaf :
  327.             //
  328.             //  There can only be one child and it has to be of the
  329.             //  element type we stored.
  330.             //
  331.             if (!childCount)
  332.                 return 0;
  333.             if ((children[0]->getURI() != fFirstChild->getURI()) ||
  334.                 !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))
  335.             {
  336.                 if (!comparator.isEquivalentTo(children[0], fFirstChild))
  337.                    return 0;
  338.             }
  339.             if (childCount > 1)
  340.                 return 1;
  341.             break;
  342.         case ContentSpecNode::ZeroOrOne :
  343.             //
  344.             //  If the child count is greater than one, then obviously
  345.             //  bad. Otherwise, if its one, then the one child must be
  346.             //  of the type we stored.
  347.             //
  348.             if ((childCount == 1) &&
  349.                ((children[0]->getURI() != fFirstChild->getURI()) ||
  350.                 !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())))
  351.             {
  352.                 if(!comparator.isEquivalentTo(children[0], fFirstChild))
  353.                     return 0;
  354.             }
  355.             if (childCount > 1)
  356.                 return 1;
  357.             break;
  358.         case ContentSpecNode::ZeroOrMore :
  359.             //
  360.             //  If the child count is zero, that's fine. If its more than
  361.             //  zero, then make sure that all children are of the element
  362.             //  type that we stored.
  363.             //
  364.             if (childCount > 0)
  365.             {
  366.                 for (index = 0; index < childCount; index++)
  367.                 {
  368.                     if ((children[index]->getURI() != fFirstChild->getURI()) ||
  369.                         !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart()))
  370.                     {
  371.          if (!comparator.isEquivalentTo(children[index], fFirstChild))
  372.                             return index;
  373.                     }
  374.                 }
  375.             }
  376.             break;
  377.         case ContentSpecNode::OneOrMore :
  378.             //
  379.             //  If the child count is zero, that's an error. If its more
  380.             //  than zero, then make sure that all children are of the
  381.             //  element type that we stored.
  382.             //
  383.             if (childCount == 0)
  384.                 return 0;
  385.             for (index = 0; index < childCount; index++)
  386.             {
  387.                 if ((children[index]->getURI() != fFirstChild->getURI()) ||
  388.                     !XMLString::equals(children[index]->getLocalPart(), fFirstChild->getLocalPart()))
  389.                 {
  390.          if (!comparator.isEquivalentTo(children[index], fFirstChild))
  391.                         return index;
  392.                 }
  393.             }
  394.             break;
  395.         case ContentSpecNode::Choice :
  396.             //
  397.             //  There can only be one child, and it must be one of the
  398.             //  two types we stored.
  399.             //
  400.             if (!childCount)
  401.                 return 0;
  402.             if (((children[0]->getURI() != fFirstChild->getURI()) ||
  403.                  !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart())) &&
  404.                 ((children[0]->getURI() != fSecondChild->getURI()) ||
  405.                  !XMLString::equals(children[0]->getLocalPart(), fSecondChild->getLocalPart())))
  406.             {
  407.                  if (!comparator.isEquivalentTo(children[0], fFirstChild) &&
  408.                      !comparator.isEquivalentTo(children[0], fSecondChild) )
  409.                      return 0;
  410.             }
  411.             if (childCount > 1)
  412.                 return 1;
  413.             break;
  414.         case ContentSpecNode::Sequence :
  415.             //
  416.             //  There must be two children and they must be the two values
  417.             //  we stored, in the stored order. So first check the obvious
  418.             //  problem of an empty content, which would never be valid
  419.             //  in this content mode.
  420.             //
  421.             if (!childCount)
  422.                 return 0;
  423.             if (childCount == 2)
  424.             {
  425.                 if ((children[0]->getURI() != fFirstChild->getURI()) ||
  426.                     !XMLString::equals(children[0]->getLocalPart(), fFirstChild->getLocalPart()))
  427.                 {
  428.                     if(!comparator.isEquivalentTo(children[0], fFirstChild))
  429.                         return 0;
  430.                 }
  431.                 if ((children[1]->getURI() != fSecondChild->getURI()) ||
  432.                     !XMLString::equals(children[1]->getLocalPart(), fSecondChild->getLocalPart()))
  433.                 {
  434.                     if (!comparator.isEquivalentTo(children[1], fSecondChild))
  435.                         return 1;
  436.                 }
  437.             }
  438.             else
  439.             {
  440.                 if (childCount > 2)
  441.                 {
  442.                     return 2;
  443.                 }
  444.                 return childCount;
  445.             }
  446.             break;
  447.         default :
  448.             ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMSpecType);
  449.             break;
  450.     }
  451.     return -1;
  452. }
  453. ContentLeafNameTypeVector* SimpleContentModel::getContentLeafNameTypeVector() const
  454. {
  455.     return 0;
  456. }
  457. void SimpleContentModel::checkUniqueParticleAttribution
  458.     (
  459.         SchemaGrammar*    const pGrammar
  460.       , GrammarResolver*  const pGrammarResolver
  461.       , XMLStringPool*    const pStringPool
  462.       , XMLValidator*     const pValidator
  463.       , unsigned int*     const pContentSpecOrgURI
  464.     )
  465. {
  466.     // rename back
  467.     unsigned int orgURIIndex = 0;
  468.     orgURIIndex = fFirstChild->getURI();
  469.     if ((orgURIIndex != XMLContentModel::gEOCFakeId) &&
  470.         (orgURIIndex != XMLElementDecl::fgInvalidElemId) &&
  471.         (orgURIIndex != XMLElementDecl::fgPCDataElemId))
  472.         fFirstChild->setURI(pContentSpecOrgURI[orgURIIndex]);
  473.     orgURIIndex = fSecondChild->getURI();
  474.     if ((orgURIIndex != XMLContentModel::gEOCFakeId) &&
  475.         (orgURIIndex != XMLElementDecl::fgInvalidElemId) &&
  476.         (orgURIIndex != XMLElementDecl::fgPCDataElemId))
  477.         fSecondChild->setURI(pContentSpecOrgURI[orgURIIndex]);
  478.     // only possible violation is when it's a choice
  479.     if (fOp == ContentSpecNode::Choice) {
  480.         SubstitutionGroupComparator comparator(pGrammarResolver, pStringPool);
  481.         if (XercesElementWildcard::conflict(pGrammar,
  482.                                             ContentSpecNode::Leaf,
  483.                                             fFirstChild,
  484.                                             ContentSpecNode::Leaf,
  485.                                             fSecondChild,
  486.                                             &comparator))
  487.             pValidator->emitError(XMLValid::UniqueParticleAttributionFail,
  488.                                   fFirstChild->getRawName(),
  489.                                   fSecondChild->getRawName());
  490.     }
  491. }
  492. XERCES_CPP_NAMESPACE_END