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

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 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: ComplexTypeInfo.cpp,v $
  58.  * Revision 1.24  2001/11/21 14:30:13  knoaman
  59.  * Fix for UPA checking.
  60.  *
  61.  * Revision 1.23  2001/11/15 17:10:19  knoaman
  62.  * Particle derivation checking support.
  63.  *
  64.  * Revision 1.22  2001/11/07 21:50:28  tng
  65.  * Fix comment log that lead to error.
  66.  *
  67.  * Revision 1.21  2001/11/07 21:12:15  tng
  68.  * Performance: Create QName in ContentSpecNode only if it is a leaf/Any/PCDataNode.
  69.  *
  70.  * Revision 1.20  2001/10/12 18:08:57  tng
  71.  * make sure the second node exists before calling getType
  72.  *
  73.  * Revision 1.19  2001/10/04 15:08:56  knoaman
  74.  * Add support for circular import.
  75.  *
  76.  * Revision 1.18  2001/09/05 20:49:11  knoaman
  77.  * Fix for complexTypes with mixed content model.
  78.  *
  79.  * Revision 1.17  2001/08/29 21:27:07  knoaman
  80.  * no message
  81.  *
  82.  * Revision 1.16  2001/08/28 20:43:52  knoaman
  83.  * Fix for content spec node adoption.
  84.  *
  85.  * Revision 1.15  2001/08/27 23:04:02  knoaman
  86.  * Handle deletion of spec node tree created during UPA checking.
  87.  *
  88.  * Revision 1.14  2001/08/27 20:48:45  knoaman
  89.  * Make the UPA rename before the content model expansion.
  90.  *
  91.  * Revision 1.13  2001/08/27 20:14:42  knoaman
  92.  * Validate attributes in <all>, <redefine>, <group> and <attributeGroup> declarations.
  93.  * Misc. fixes.
  94.  *
  95.  * Revision 1.12  2001/08/24 12:48:48  tng
  96.  * Schema: AllContentModel
  97.  *
  98.  * Revision 1.11  2001/08/23 11:54:26  tng
  99.  * Add newline at the end and various typo fixes.
  100.  *
  101.  * Revision 1.10  2001/08/21 18:14:55  knoaman
  102.  * Defer creation of spec node.
  103.  *
  104.  * Revision 1.9  2001/08/21 16:06:11  tng
  105.  * Schema: Unique Particle Attribution Constraint Checking.
  106.  *
  107.  * Revision 1.8  2001/08/09 15:23:16  knoaman
  108.  * add support for <anyAttribute> declaration.
  109.  *
  110.  * Revision 1.7  2001/07/24 18:33:46  knoaman
  111.  * Added support for <group> + extra constraint checking for complexType
  112.  *
  113.  * Revision 1.6  2001/06/05 13:59:53  knoaman
  114.  * Fixes to include and import.
  115.  *
  116.  * Revision 1.5  2001/05/11 13:27:32  tng
  117.  * Copyright update.
  118.  *
  119.  * Revision 1.4  2001/05/10 17:49:40  tng
  120.  * Schema: SchemaValidator fixes
  121.  *
  122.  * Revision 1.3  2001/05/10 16:33:12  knoaman
  123.  * Traverse Schema Part III + error messages.
  124.  *
  125.  * Revision 1.2  2001/05/03 20:34:41  tng
  126.  * Schema: SchemaValidator update
  127.  *
  128.  * Revision 1.1  2001/04/19 17:43:14  knoaman
  129.  * More schema implementation classes.
  130.  *
  131.  */
  132. // ---------------------------------------------------------------------------
  133. //  Includes
  134. // ---------------------------------------------------------------------------
  135. #include <framework/XMLBuffer.hpp>
  136. #include <validators/schema/ComplexTypeInfo.hpp>
  137. #include <validators/schema/SchemaAttDefList.hpp>
  138. #include <validators/common/AllContentModel.hpp>
  139. #include <validators/common/ContentSpecNode.hpp>
  140. #include <validators/common/DFAContentModel.hpp>
  141. #include <validators/common/MixedContentModel.hpp>
  142. #include <validators/common/SimpleContentModel.hpp>
  143. // ---------------------------------------------------------------------------
  144. //  ComplexTypeInfo: Constructors and Destructor
  145. // ---------------------------------------------------------------------------
  146. ComplexTypeInfo::ComplexTypeInfo()
  147.     : fAbstract(false)
  148.     , fAdoptContentSpec(true)
  149.     , fAttWithTypeId(false)
  150.     , fDerivedBy(0)
  151.     , fBlockSet(0)
  152.     , fFinalSet(0)
  153.     , fScopeDefined(Grammar::TOP_LEVEL_SCOPE)
  154.     , fElementId(XMLElementDecl::fgInvalidElemId)
  155.     , fContentType(SchemaElementDecl::Empty)
  156.     , fTypeName(0)
  157.     , fBaseDatatypeValidator(0)
  158.     , fDatatypeValidator(0)
  159.     , fBaseComplexTypeInfo(0)
  160.     , fContentSpec(0)
  161.     , fAttWildCard(0)
  162.     , fAttDefs(0)
  163.     , fAttList(0)
  164.     , fElements(0)
  165.     , fContentModel(0)
  166.     , fFormattedModel(0)
  167.     , fContentSpecOrgURI(0)
  168.     , fUniqueURI(0)
  169.     , fContentSpecOrgURISize(16)
  170.     , fSpecNodesToDelete(0)
  171. {
  172. }
  173. ComplexTypeInfo::~ComplexTypeInfo()
  174. {
  175.     delete [] fTypeName;
  176.     if (fAdoptContentSpec) {
  177.         delete fContentSpec;
  178.     }
  179.     delete fAttWildCard;
  180.     delete fAttDefs;
  181.     delete fAttList;
  182.     delete fElements;
  183.     delete fSpecNodesToDelete;
  184.     delete fContentModel;
  185.     delete [] fFormattedModel;
  186.     delete [] fContentSpecOrgURI;
  187. }
  188. // ---------------------------------------------------------------------------
  189. //  ComplexTypeInfo: Setter methods
  190. // ---------------------------------------------------------------------------
  191. void ComplexTypeInfo::addAttDef(SchemaAttDef* const toAdd) {
  192.     // Fault in the att list if required
  193.     if (!fAttDefs)
  194.         faultInAttDefList();
  195.     // Tell this guy the element id of its parent (us)
  196.     toAdd->setElemId(getElementId());
  197.     fAttDefs->put((void*)(toAdd->getAttName()->getLocalPart()),
  198.                           toAdd->getAttName()->getURI(), toAdd);
  199. }
  200. void ComplexTypeInfo::setContentSpec(ContentSpecNode* const toAdopt) {
  201.     if (fContentSpec && fAdoptContentSpec) {
  202.         delete fContentSpec;
  203.     }
  204.     fContentSpec = toAdopt;
  205. }
  206. // ---------------------------------------------------------------------------
  207. //  ComplexTypeInfo: Getter methods
  208. // ---------------------------------------------------------------------------
  209. XMLAttDefList& ComplexTypeInfo::getAttDefList() const
  210. {
  211.     if (!fAttList)
  212.     {
  213.         // If the att def list is not made yet, then fault it in too
  214.         if (!fAttDefs)
  215.             faultInAttDefList();
  216.         ((ComplexTypeInfo*)this)->fAttList = new SchemaAttDefList(fAttDefs);
  217.     }
  218.     // Reset it before we return it
  219.     fAttList->Reset();
  220.     return *fAttList;
  221. }
  222. const XMLCh*
  223. ComplexTypeInfo::getFormattedContentModel() const
  224. {
  225.     //
  226.     //  If its not already built, then call the protected virtual method
  227.     //  to allow the derived class to build it (since only it knows.)
  228.     //  Otherwise, just return the previously formatted methods.
  229.     //
  230.     //  Since we are faulting this in, within a const getter, we have to
  231.     //  cast off the const-ness.
  232.     //
  233.     if (!fFormattedModel)
  234.         ((ComplexTypeInfo*)this)->fFormattedModel = formatContentModel();
  235.     return fFormattedModel;
  236. }
  237. // ---------------------------------------------------------------------------
  238. //  ComplexTypeInfo: Helper methods
  239. // ---------------------------------------------------------------------------
  240. XMLAttDef* ComplexTypeInfo::findAttr(const XMLCh* const qName
  241.                                      , const unsigned int uriId
  242.                                      , const XMLCh* const baseName
  243.                                      , const XMLCh* const prefix
  244.                                      , const XMLElementDecl::LookupOpts   options
  245.                                      , bool&              wasAdded) const
  246. {
  247.     SchemaAttDef* retVal = 0;
  248.     // If no att list faulted in yet, then it cannot exist
  249.     if (fAttDefs)
  250.         retVal = fAttDefs->get(baseName, uriId);
  251.     // Fault it in if not found and ask to add it
  252.     if (!retVal && (options == XMLElementDecl::AddIfNotFound))
  253.     {
  254.         // Fault in the list itself if not already
  255.         if (!fAttDefs)
  256.             faultInAttDefList();
  257.         // And add a default attribute for this name
  258.         retVal = new SchemaAttDef(prefix, baseName, uriId);
  259.         retVal->setElemId(getElementId());
  260.         fAttDefs->put((void*)baseName, uriId, retVal);
  261.         wasAdded = true;
  262.     }
  263.      else
  264.     {
  265.         wasAdded = false;
  266.     }
  267.     return retVal;
  268. }
  269. bool ComplexTypeInfo::resetDefs() {
  270.     // If the collection hasn't been faulted in, then no att defs
  271.     if (!fAttDefs)
  272.         return false;
  273.     //
  274.     //  Ok, run through them and clear the 'provided' flag on each of them.
  275.     //  This lets the scanner use them to track which has been provided and
  276.     //  which have not.
  277.     //
  278.     RefHash2KeysTableOfEnumerator<SchemaAttDef> enumDefs(fAttDefs);
  279.     while (enumDefs.hasMoreElements())
  280.         enumDefs.nextElement().setProvided(false);
  281.     return true;
  282. }
  283. void ComplexTypeInfo::checkUniqueParticleAttribution (SchemaGrammar*    const pGrammar,
  284.                                                       GrammarResolver*  const pGrammarResolver,
  285.                                                       XMLStringPool*    const pStringPool,
  286.                                                       XMLValidator*     const pValidator)
  287. {
  288.     if (fContentSpec) {
  289.         ContentSpecNode* specNode = new ContentSpecNode(*fContentSpec);
  290.         XMLContentModel* cm = makeContentModel(true, specNode);
  291.         if (cm) {
  292.             cm->checkUniqueParticleAttribution(pGrammar, pGrammarResolver, pStringPool, pValidator, fContentSpecOrgURI);
  293.             delete cm;
  294.         }
  295.         fSpecNodesToDelete->removeAllElements();
  296.     }
  297. }
  298. // ---------------------------------------------------------------------------
  299. //  ComplexTypeInfo: Private Helper methods
  300. // ---------------------------------------------------------------------------
  301. void ComplexTypeInfo::faultInAttDefList() const
  302. {
  303.     // Use a hash modulus of 29 and tell it owns its elements
  304.     ((ComplexTypeInfo*)this)->fAttDefs =
  305.                     new RefHash2KeysTableOf<SchemaAttDef>(29, true);
  306. }
  307. XMLCh* ComplexTypeInfo::formatContentModel() const
  308. {
  309.     XMLCh* newValue = 0;
  310.     if (fContentType == SchemaElementDecl::Any)
  311.     {
  312.         newValue = XMLString::replicate(XMLUni::fgAnyString);
  313.     }
  314.      else if (fContentType == SchemaElementDecl::Empty)
  315.     {
  316.         newValue = XMLString::replicate(XMLUni::fgEmptyString);
  317.     }
  318.      else
  319.     {
  320.         //
  321.         //  Use a temp XML buffer to format into. Content models could be
  322.         //  pretty long, but very few will be longer than one K. The buffer
  323.         //  will expand to handle the more pathological ones.
  324.         //
  325.         const ContentSpecNode* specNode = fContentSpec;
  326.         if (specNode) {
  327.             XMLBuffer bufFmt;
  328.             specNode->formatSpec(bufFmt);
  329.             newValue = XMLString::replicate(bufFmt.getRawBuffer());
  330.         }
  331.     }
  332.     return newValue;
  333. }
  334. XMLContentModel* ComplexTypeInfo::makeContentModel(const bool checkUPA, ContentSpecNode* const specNode)
  335. {
  336.     if ((specNode || fContentSpec) && !fSpecNodesToDelete) {
  337.         fSpecNodesToDelete = new RefVectorOf<ContentSpecNode>(8);
  338.     }
  339.     // expand the content spec first
  340.     ContentSpecNode* aSpecNode = specNode;
  341.     if (aSpecNode) {
  342.         fContentSpecOrgURI = new unsigned int[fContentSpecOrgURISize];
  343.         aSpecNode = convertContentSpecTree(aSpecNode, checkUPA);
  344.         fSpecNodesToDelete->addElement(aSpecNode);
  345.     }
  346.     else {
  347.         aSpecNode = convertContentSpecTree(fContentSpec, checkUPA);
  348.         if (aSpecNode != fContentSpec) {
  349.             if (aSpecNode == fContentSpec->getFirst() && !fAdoptContentSpec)
  350.                 fAdoptContentSpec = false;
  351.             else
  352.                 fAdoptContentSpec = true;
  353.             fContentSpec = aSpecNode;
  354.         }
  355.     }
  356.     XMLContentModel* cmRet = 0;
  357.     if (fContentType == SchemaElementDecl::Simple) {
  358.        // just return nothing
  359.     }
  360.     else if (fContentType == SchemaElementDecl::Mixed_Simple)
  361.     {
  362.         //
  363.         //  Just create a mixel content model object. This type of
  364.         //  content model is optimized for mixed content validation.
  365.         //
  366.         cmRet = new MixedContentModel(false, aSpecNode);
  367.     }
  368.     else if (fContentType == SchemaElementDecl::Mixed_Complex) {
  369.             cmRet = createChildModel(aSpecNode, true);
  370.     }
  371.     else if (fContentType == SchemaElementDecl::Children)
  372.     {
  373.         //
  374.         //  This method will create an optimal model for the complexity
  375.         //  of the element's defined model. If its simple, it will create
  376.         //  a SimpleContentModel object. If its a simple list, it will
  377.         //  create a SimpleListContentModel object. If its complex, it
  378.         //  will create a DFAContentModel object.
  379.         //
  380.          cmRet = createChildModel(aSpecNode, false);
  381.     }
  382.      else
  383.     {
  384.         ThrowXML(RuntimeException, XMLExcepts::CM_MustBeMixedOrChildren);
  385.     }
  386.     return cmRet;
  387. }
  388. // ---------------------------------------------------------------------------
  389. //  SchemaElementDecl: Private helper methods
  390. // ---------------------------------------------------------------------------
  391. XMLContentModel* ComplexTypeInfo::createChildModel(ContentSpecNode* specNode, const bool isMixed)
  392. {
  393.     if(!specNode)
  394.         ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMSpecType);
  395.     ContentSpecNode::NodeTypes specType = specNode->getType();
  396.     //
  397.     //  Do a sanity check that the node is does not have a PCDATA id. Since,
  398.     //  if it was, it should have already gotten taken by the Mixed model.
  399.     //
  400.     if (specNode->getElement()) {
  401.         if (specNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId)
  402.             ThrowXML(RuntimeException, XMLExcepts::CM_NoPCDATAHere);
  403.     }
  404.     //
  405.     //  According to the type of node, we will create the correct type of
  406.     //  content model.
  407.     //
  408.     if (((specType & 0x0f) == ContentSpecNode::Any) ||
  409.        ((specType & 0x0f) == ContentSpecNode::Any_Other) ||
  410.        ((specType & 0x0f) == ContentSpecNode::Any_NS)) {
  411.        // let fall through to build a DFAContentModel
  412.     }
  413.     else if (isMixed)
  414.     {
  415.         if (specType == ContentSpecNode::All) {
  416.             // All the nodes under an ALL must be additional ALL nodes and
  417.             // ELEMENTs (or ELEMENTs under ZERO_OR_ONE nodes.)
  418.             // We collapse the ELEMENTs into a single vector.
  419.             return new AllContentModel(specNode, true);
  420.         }
  421.         else if (specType == ContentSpecNode::ZeroOrOne) {
  422.             // An ALL node can appear under a ZERO_OR_ONE node.
  423.             if (specNode->getFirst()->getType() == ContentSpecNode::All) {
  424.                 return new AllContentModel(specNode->getFirst(), true);
  425.             }
  426.         }
  427.         // otherwise, let fall through to build a DFAContentModel
  428.     }
  429.      else if (specType == ContentSpecNode::Leaf)
  430.     {
  431.         // Create a simple content model
  432.         return new SimpleContentModel
  433.         (
  434.             false
  435.             , specNode->getElement()
  436.             , 0
  437.             , ContentSpecNode::Leaf
  438.         );
  439.     }
  440.      else if ((specType == ContentSpecNode::Choice)
  441.           ||  (specType == ContentSpecNode::Sequence))
  442.     {
  443.         //
  444.         //  Lets see if both of the children are leafs. If so, then it has to
  445.         //  be a simple content model
  446.         //
  447.         if ((specNode->getFirst()->getType() == ContentSpecNode::Leaf)
  448.         &&  (specNode->getSecond())
  449.         &&  (specNode->getSecond()->getType() == ContentSpecNode::Leaf))
  450.         {
  451.             return new SimpleContentModel
  452.             (
  453.                 false
  454.                 , specNode->getFirst()->getElement()
  455.                 , specNode->getSecond()->getElement()
  456.                 , specType
  457.             );
  458.         }
  459.     }
  460.      else if ((specType == ContentSpecNode::OneOrMore)
  461.           ||  (specType == ContentSpecNode::ZeroOrMore)
  462.           ||  (specType == ContentSpecNode::ZeroOrOne))
  463.     {
  464.         //
  465.         //  Its a repetition, so see if its one child is a leaf. If so its a
  466.         //  repetition of a single element, so we can do a simple content
  467.         //  model for that.
  468.         //
  469.         if (specNode->getFirst()->getType() == ContentSpecNode::Leaf)
  470.         {
  471.             return new SimpleContentModel
  472.             (
  473.                 false
  474.                 , specNode->getFirst()->getElement()
  475.                 , 0
  476.                 , specType
  477.             );
  478.         }
  479.         else if (specNode->getFirst()->getType() == ContentSpecNode::All)
  480.             return new AllContentModel(specNode->getFirst(), false);
  481.     }
  482.     else if (specType == ContentSpecNode::All)
  483.         return new AllContentModel(specNode, false);
  484.     else
  485.     {
  486.         ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMSpecType);
  487.     }
  488.     // Its not any simple type of content, so create a DFA based content model
  489.     return new DFAContentModel(false, specNode, isMixed);
  490. }
  491. ContentSpecNode*
  492. ComplexTypeInfo::convertContentSpecTree(ContentSpecNode* const curNode,
  493.                                         const bool checkUPA) {
  494.     if (!curNode)
  495.         return 0;
  496.     const ContentSpecNode::NodeTypes curType = curNode->getType();
  497.     // When checking Unique Particle Attribution, rename leaf elements
  498.     if (checkUPA) {
  499.         if (curNode->getElement()) {
  500.             fContentSpecOrgURI[fUniqueURI] = curNode->getElement()->getURI();
  501.             curNode->getElement()->setURI(fUniqueURI);
  502.             fUniqueURI++;
  503.         }
  504.         if (fUniqueURI == fContentSpecOrgURISize)
  505.             resizeContentSpecOrgURI();
  506.     }
  507.     // Get the spec type of the passed node
  508.     int minOccurs = curNode->getMinOccurs();
  509.     int maxOccurs = curNode->getMaxOccurs();
  510.     ContentSpecNode* retNode = curNode;
  511.     if ((curType & 0x0f) == ContentSpecNode::Any
  512.         || (curType & 0x0f) == ContentSpecNode::Any_Other
  513.         || (curType & 0x0f) == ContentSpecNode::Any_NS
  514.         || curType == ContentSpecNode::Leaf)
  515.     {
  516.         retNode =  expandContentModel(curNode, minOccurs, maxOccurs);
  517.     }
  518.     else if ((curType == ContentSpecNode::Choice)
  519.         ||   (curType == ContentSpecNode::All)
  520.         ||   (curType == ContentSpecNode::Sequence))
  521.     {
  522.         ContentSpecNode* childNode = curNode->getFirst();
  523.         ContentSpecNode* leftNode = convertContentSpecTree(childNode, checkUPA);
  524.         ContentSpecNode* rightNode = curNode->getSecond();
  525.         if (!rightNode) {
  526.             retNode = expandContentModel(leftNode, minOccurs, maxOccurs);
  527.             curNode->setAdoptFirst(false);
  528.             delete curNode;
  529.             return retNode;
  530.         }
  531.         if (leftNode != childNode) {
  532.             curNode->setAdoptFirst(false);
  533.             curNode->setFirst(leftNode);
  534.             curNode->setAdoptFirst(true);
  535.         }
  536.         childNode = rightNode;
  537.         rightNode =  convertContentSpecTree(childNode, checkUPA);
  538.         if (rightNode != childNode) {
  539.             curNode->setAdoptSecond(false);
  540.             curNode->setSecond(rightNode);
  541.             curNode->setAdoptSecond(true);
  542.         }
  543.         retNode =  expandContentModel(curNode, minOccurs, maxOccurs);
  544.     }
  545.     return retNode;
  546. }
  547. ContentSpecNode* ComplexTypeInfo::expandContentModel(ContentSpecNode* const specNode,
  548.                                                      const int minOccurs,
  549.                                                      const int maxOccurs)
  550. {
  551.     if (!specNode) {
  552.         return 0;
  553.     }
  554.     ContentSpecNode* saveNode = specNode;
  555.     ContentSpecNode* retNode = specNode;
  556.     if (minOccurs == 1 && maxOccurs == 1) {
  557.     }
  558.     else if (minOccurs == 0 && maxOccurs == 1) {
  559.         retNode = new ContentSpecNode(ContentSpecNode::ZeroOrOne, retNode, 0);
  560.     }
  561.     else if (minOccurs == 0 && maxOccurs == -1) {
  562.         retNode = new ContentSpecNode(ContentSpecNode::ZeroOrMore, retNode, 0);
  563.     }
  564.     else if (minOccurs == 1 && maxOccurs == -1) {
  565.         retNode = new ContentSpecNode(ContentSpecNode::OneOrMore, retNode, 0);
  566.     }
  567.     else if (maxOccurs == -1) {
  568.         retNode = new ContentSpecNode(ContentSpecNode::OneOrMore, retNode, 0);
  569.         for (int i=0; i < (int)(minOccurs-1); i++) {
  570.             retNode = new ContentSpecNode(ContentSpecNode::Sequence,
  571.                                           saveNode, retNode, false);
  572.         }
  573.     }
  574.     else {
  575.         if (minOccurs == 0) {
  576.             ContentSpecNode* optional =
  577.                 new ContentSpecNode(ContentSpecNode::ZeroOrOne, saveNode, 0);
  578.             retNode = optional;
  579.             for (int i=0; i < (int)(maxOccurs-minOccurs-1); i++) {
  580.                 retNode = new ContentSpecNode(ContentSpecNode::Sequence,
  581.                                               retNode, optional, true, false);
  582.             }
  583.         }
  584.         else {
  585.             if (minOccurs > 1) {
  586.                 retNode = new ContentSpecNode(ContentSpecNode::Sequence,
  587.                                               retNode, saveNode, true, false);
  588.                 for (int i=1; i < (int)(minOccurs-1); i++) {
  589.                     retNode = new ContentSpecNode(ContentSpecNode::Sequence,
  590.                                                   retNode, saveNode, true, false);
  591.                 }
  592.             }
  593.             int counter = maxOccurs-minOccurs;
  594.             if (counter > 0) {
  595.                 ContentSpecNode* optional = new ContentSpecNode(ContentSpecNode::ZeroOrOne, saveNode, 0, false);
  596.                 retNode = new ContentSpecNode(ContentSpecNode::Sequence, retNode, optional);
  597.                 for (int j=1; j < counter; j++) {
  598.                     retNode = new ContentSpecNode(ContentSpecNode::Sequence,
  599.                               retNode, optional, true, false);
  600.                 }
  601.             }
  602.         }
  603.     }
  604.     return retNode;
  605. }
  606. void ComplexTypeInfo::resizeContentSpecOrgURI() {
  607.     unsigned int newSize = fContentSpecOrgURISize * 2;
  608.     unsigned int* newContentSpecOrgURI = new unsigned int[newSize];
  609.     // Copy the existing values
  610.     unsigned int index = 0;
  611.     for (; index < fContentSpecOrgURISize; index++)
  612.         newContentSpecOrgURI[index] = fContentSpecOrgURI[index];
  613.     for (; index < newSize; index++)
  614.         newContentSpecOrgURI[index] = 0;
  615.     // Delete the old array and udpate our members
  616.     delete [] fContentSpecOrgURI;
  617.     fContentSpecOrgURI = newContentSpecOrgURI;
  618.     fContentSpecOrgURISize = newSize;
  619. }
  620. /**
  621.   * End of file ComplexTypeInfo.cpp
  622.   */