DTDElementDecl.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:13k
源码类别:

xml/soap/webservice

开发平台:

C/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.  * $Id: DTDElementDecl.cpp,v 1.17 2001/11/07 21:12:15 tng Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <util/XMLString.hpp>
  63. #include <util/XMLUniDefs.hpp>
  64. #include <util/XMLUni.hpp>
  65. #include <framework/XMLBuffer.hpp>
  66. #include <validators/common/DFAContentModel.hpp>
  67. #include <validators/common/ContentSpecNode.hpp>
  68. #include <validators/common/MixedContentModel.hpp>
  69. #include <validators/common/SimpleContentModel.hpp>
  70. #include <validators/DTD/DTDAttDefList.hpp>
  71. #include <validators/DTD/DTDElementDecl.hpp>
  72. // ---------------------------------------------------------------------------
  73. //  DTDElementDecl: Constructors and Destructor
  74. // ---------------------------------------------------------------------------
  75. DTDElementDecl::DTDElementDecl() :
  76.     fAttDefs(0)
  77.     , fAttList(0)
  78.     , fContentSpec(0)
  79.     , fModelType(Any)
  80.     , fContentModel(0)  
  81.     , fFormattedModel(0)      
  82. {
  83. }
  84. DTDElementDecl::DTDElementDecl( const   XMLCh* const              elemRawName
  85.                               , const   unsigned int              uriId
  86.                               , const DTDElementDecl::ModelTypes  type) :
  87.     fAttDefs(0)
  88.     , fAttList(0)
  89.     , fContentSpec(0)
  90.     , fModelType(type)
  91.     , fContentModel(0)  
  92.     , fFormattedModel(0)        
  93. {
  94.     setElementName(elemRawName, uriId);
  95. }
  96. DTDElementDecl::DTDElementDecl( QName* const                elementName
  97.                               , const DTDElementDecl::ModelTypes  type) :
  98.     fAttDefs(0)
  99.     , fAttList(0)
  100.     , fContentSpec(0)
  101.     , fModelType(type)
  102.     , fContentModel(0)      
  103.     , fFormattedModel(0)    
  104. {
  105.     setElementName(elementName);
  106. }
  107. DTDElementDecl::~DTDElementDecl()
  108. {
  109.     delete fAttDefs;
  110.     delete fAttList;
  111.     delete fContentSpec;
  112.     delete fContentModel;    
  113.     delete [] fFormattedModel;    
  114. }
  115. // ---------------------------------------------------------------------------
  116. //  The virtual element decl interface
  117. // ---------------------------------------------------------------------------
  118. XMLAttDef* DTDElementDecl::findAttr(const   XMLCh* const    qName
  119.                                     , const unsigned int    uriId
  120.                                     , const XMLCh* const    baseName
  121.                                     , const XMLCh* const    prefix
  122.                                     , const LookupOpts      options
  123.                                     ,       bool&           wasAdded) const
  124. {
  125.     DTDAttDef* retVal = 0;
  126.     // If no att list faulted in yet, then it cannot exist
  127.     if (fAttDefs)
  128.         retVal = fAttDefs->get(qName);
  129.     // Fault it in if not found and ask to add it
  130.     if (!retVal && (options == XMLElementDecl::AddIfNotFound))
  131.     {
  132.         // Fault in the list itself if not already
  133.         if (!fAttDefs)
  134.             faultInAttDefList();
  135.         // And add a default attribute for this name
  136.         retVal = new DTDAttDef(qName);
  137.         retVal->setElemId(getId());
  138.         fAttDefs->put((void*)retVal->getFullName(), retVal);
  139.         wasAdded = true;
  140.     }
  141.      else
  142.     {
  143.         wasAdded = false;
  144.     }
  145.     return retVal;
  146. }
  147. XMLAttDefList& DTDElementDecl::getAttDefList() const
  148. {
  149.     if (!fAttList)
  150.     {
  151.         // If the att def list is not made yet, then fault it in too
  152.         if (!fAttDefs)
  153.             faultInAttDefList();
  154.         ((DTDElementDecl*)this)->fAttList = new DTDAttDefList(fAttDefs);
  155.     }
  156.     // Reset it before we return it
  157.     fAttList->Reset();
  158.     return *fAttList;
  159. }
  160. XMLElementDecl::CharDataOpts DTDElementDecl::getCharDataOpts() const
  161. {
  162.     XMLElementDecl::CharDataOpts retVal;
  163.     switch(fModelType)
  164.     {
  165.         case Children :
  166.             retVal = XMLElementDecl::SpacesOk;
  167.             break;
  168.         case Empty :
  169.             retVal = XMLElementDecl::NoCharData;
  170.             break;
  171.         default :
  172.             retVal = XMLElementDecl::AllCharData;
  173.             break;
  174.     }
  175.     return retVal;
  176. }
  177. bool DTDElementDecl::hasAttDefs() const
  178. {
  179.     // If the collection hasn't been faulted in, then no att defs
  180.     if (!fAttDefs)
  181.         return false;
  182.     return !fAttDefs->isEmpty();
  183. }
  184. bool DTDElementDecl::resetDefs()
  185. {
  186.     // If the collection hasn't been faulted in, then no att defs
  187.     if (!fAttDefs)
  188.         return false;
  189.     //
  190.     //  Ok, run through them and clear the 'provided' flag on each of them.
  191.     //  This lets the scanner use them to track which has been provided and
  192.     //  which have not.
  193.     //
  194.     RefHashTableOfEnumerator<DTDAttDef> enumDefs(fAttDefs);
  195.     while (enumDefs.hasMoreElements())
  196.         enumDefs.nextElement().setProvided(false);
  197.     return true;
  198. }
  199. void
  200. DTDElementDecl::setContentSpec(ContentSpecNode* toAdopt)
  201. {
  202.     delete fContentSpec;
  203.     fContentSpec = toAdopt;
  204. }
  205. const XMLCh*
  206. DTDElementDecl::getFormattedContentModel() const
  207. {
  208.     //
  209.     //  If its not already built, then call the protected virtual method
  210.     //  to allow the derived class to build it (since only it knows.)
  211.     //  Otherwise, just return the previously formatted methods.
  212.     //
  213.     //  Since we are faulting this in, within a const getter, we have to
  214.     //  cast off the const-ness.
  215.     //
  216.     if (!fFormattedModel)
  217.         ((DTDElementDecl*)this)->fFormattedModel = formatContentModel();
  218.     return fFormattedModel;
  219. }
  220. // ---------------------------------------------------------------------------
  221. //  DTDElementDecl: Getter methods
  222. // ---------------------------------------------------------------------------
  223. const DTDAttDef* DTDElementDecl::getAttDef(const XMLCh* const attName) const
  224. {
  225.     // If no list, then return a null
  226.     if (!fAttDefs)
  227.         return 0;
  228.     return fAttDefs->get(attName);
  229. }
  230. DTDAttDef* DTDElementDecl::getAttDef(const XMLCh* const attName)
  231. {
  232.     // If no list, then return a null
  233.     if (!fAttDefs)
  234.         return 0;
  235.     return fAttDefs->get(attName);
  236. }
  237. // ---------------------------------------------------------------------------
  238. //  DTDElementDecl: Implementation of the protected virtual interface
  239. // ---------------------------------------------------------------------------
  240. void DTDElementDecl::addAttDef(DTDAttDef* const toAdd)
  241. {
  242.     // Fault in the att list if required
  243.     if (!fAttDefs)
  244.             faultInAttDefList();
  245.     // Tell this guy the element id of its parent (us)
  246.     toAdd->setElemId(getId());
  247.     fAttDefs->put((void*)(toAdd->getFullName()), toAdd);
  248. }
  249. // ---------------------------------------------------------------------------
  250. //  DTDElementDecl: Private helper methods
  251. // ---------------------------------------------------------------------------
  252. XMLCh*
  253. DTDElementDecl::formatContentModel() const
  254. {
  255.     XMLCh* newValue = 0;
  256.     if (fModelType == Any)
  257.     {
  258.         newValue = XMLString::replicate(XMLUni::fgAnyString);
  259.     }
  260.      else if (fModelType == Empty)
  261.     {
  262.         newValue = XMLString::replicate(XMLUni::fgEmptyString);
  263.     }
  264.      else
  265.     {
  266.         //
  267.         //  Use a temp XML buffer to format into. Content models could be
  268.         //  pretty long, but very few will be longer than one K. The buffer
  269.         //  will expand to handle the more pathological ones.
  270.         //
  271.         XMLBuffer bufFmt;
  272.         getContentSpec()->formatSpec(bufFmt);
  273.         newValue = XMLString::replicate(bufFmt.getRawBuffer());
  274.     }
  275.     return newValue;
  276. }
  277. XMLContentModel* DTDElementDecl::makeContentModel()
  278. {
  279.     XMLContentModel* cmRet = 0;
  280.     if (fModelType == Mixed_Simple)
  281.     {
  282.         //
  283.         //  Just create a mixel content model object. This type of
  284.         //  content model is optimized for mixed content validation.
  285.         //
  286.         cmRet = new MixedContentModel(true, this->getContentSpec());
  287.     }
  288.      else if (fModelType == Children)
  289.     {
  290.         //
  291.         //  This method will create an optimal model for the complexity
  292.         //  of the element's defined model. If its simple, it will create
  293.         //  a SimpleContentModel object. If its a simple list, it will
  294.         //  create a SimpleListContentModel object. If its complex, it
  295.         //  will create a DFAContentModel object.
  296.         //
  297.         cmRet = createChildModel();
  298.     }
  299.      else
  300.     {
  301.         ThrowXML(RuntimeException, XMLExcepts::CM_MustBeMixedOrChildren);
  302.     }
  303.     return cmRet;
  304. }
  305. XMLContentModel* DTDElementDecl::createChildModel()
  306. {
  307.     // Get the content spec node of the element
  308.     ContentSpecNode* specNode = getContentSpec();
  309.     if(!specNode)
  310.         ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMSpecType);
  311.     //
  312.     //  Do a sanity check that the node does not have a PCDATA id. Since,
  313.     //  if it was, it should have already gotten taken by the Mixed model.
  314.     //
  315.     if (specNode->getElement()) {
  316.         if (specNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId)
  317.             ThrowXML(RuntimeException, XMLExcepts::CM_NoPCDATAHere);
  318.     }
  319.     //
  320.     //  According to the type of node, we will create the correct type of
  321.     //  content model.
  322.     //
  323.     if (specNode->getType() == ContentSpecNode::Leaf)
  324.     {
  325.         // Create a simple content model
  326.         return new SimpleContentModel
  327.         (
  328.             true
  329.             , specNode->getElement()
  330.             , 0
  331.             , ContentSpecNode::Leaf
  332.         );
  333.     }
  334.      else if ((specNode->getType() == ContentSpecNode::Choice)
  335.           ||  (specNode->getType() == ContentSpecNode::Sequence))
  336.     {
  337.         //
  338.         //  Lets see if both of the children are leafs. If so, then it has to
  339.         //  be a simple content model
  340.         //
  341.         if ((specNode->getFirst()->getType() == ContentSpecNode::Leaf)
  342.         &&  (specNode->getSecond()->getType() == ContentSpecNode::Leaf))
  343.         {
  344.             return new SimpleContentModel
  345.             (
  346.                 true
  347.                 , specNode->getFirst()->getElement()
  348.                 , specNode->getSecond()->getElement()
  349.                 , specNode->getType()
  350.             );
  351.         }
  352.     }
  353.      else if ((specNode->getType() == ContentSpecNode::OneOrMore)
  354.           ||  (specNode->getType() == ContentSpecNode::ZeroOrMore)
  355.           ||  (specNode->getType() == ContentSpecNode::ZeroOrOne))
  356.     {
  357.         //
  358.         //  Its a repetition, so see if its one child is a leaf. If so its a
  359.         //  repetition of a single element, so we can do a simple content
  360.         //  model for that.
  361.         //
  362.         if (specNode->getFirst()->getType() == ContentSpecNode::Leaf)
  363.         {
  364.             return new SimpleContentModel
  365.             (
  366.                 true
  367.                 , specNode->getFirst()->getElement()
  368.                 , 0
  369.                 , specNode->getType()
  370.             );
  371.         }
  372.     }
  373.      else
  374.     {
  375.         ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMSpecType);
  376.     }
  377.     // Its not any simple type of content, so create a DFA based content model
  378.     return new DFAContentModel(true, this->getContentSpec());
  379. }
  380. void DTDElementDecl::faultInAttDefList() const
  381. {
  382.     // Use a hash modulus of 29 and tell it owns its elements
  383.     ((DTDElementDecl*)this)->fAttDefs = new RefHashTableOf<DTDAttDef>(29, true);
  384. }