1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xerces" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, International
  53. * Business Machines, Inc., http://www.apache.org. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package com.sun.org.apache.xerces.internal.impl.dtd.models;
  58. import com.sun.org.apache.xerces.internal.xni.QName;
  59. import com.sun.org.apache.xerces.internal.impl.dtd.XMLContentSpec;
  60. /**
  61. * @version $Id: SimpleContentModel.java,v 1.4 2002/05/29 17:59:37 neilg Exp $
  62. *
  63. * SimpleContentModel is a derivative of the abstract content model base
  64. * class that handles a small set of simple content models that are just
  65. * way overkill to give the DFA treatment.
  66. * <p>
  67. * This class handles the following scenarios:
  68. * <ul>
  69. * <li> a
  70. * <li> a?
  71. * <li> a*
  72. * <li> a+
  73. * <li> a,b
  74. * <li> a|b
  75. * </ul>
  76. * <p>
  77. * These all involve a unary operation with one element type, or a binary
  78. * operation with two elements. These are very simple and can be checked
  79. * in a simple way without a DFA and without the overhead of setting up a
  80. * DFA for such a simple check.
  81. *
  82. */
  83. public class SimpleContentModel
  84. implements ContentModelValidator {
  85. //
  86. // Constants
  87. //
  88. /** CHOICE */
  89. public static final short CHOICE = -1;
  90. /** SEQUENCE */
  91. public static final short SEQUENCE = -1;
  92. //
  93. // Data
  94. //
  95. /**
  96. * The element decl pool indices of the first (and optional second)
  97. * child node. The operation code tells us whether the second child
  98. * is used or not.
  99. */
  100. private QName fFirstChild = new QName();
  101. /**
  102. * The element decl pool indices of the first (and optional second)
  103. * child node. The operation code tells us whether the second child
  104. * is used or not.
  105. */
  106. private QName fSecondChild = new QName();
  107. /**
  108. * The operation that this object represents. Since this class only
  109. * does simple contents, there is only ever a single operation
  110. * involved (i.e. the children of the operation are always one or
  111. * two leafs.) This is one of the XMLDTDParams.CONTENTSPECNODE_XXX values.
  112. */
  113. private int fOperator;
  114. /* this is the EquivClassComparator object */
  115. //private EquivClassComparator comparator = null;
  116. //
  117. // Constructors
  118. //
  119. /**
  120. * Constructs a simple content model.
  121. *
  122. * @param operator The content model operator.
  123. * @param firstChild The first child index.
  124. * @param secondChild The second child index.
  125. * @param dtd if it is for a DTDGrammar.
  126. *
  127. */
  128. public SimpleContentModel(short operator, QName firstChild, QName secondChild) {
  129. //
  130. // Store away the children and operation. This is all we need to
  131. // do the content model check.
  132. //
  133. // The operation is one of the ContentSpecNode.NODE_XXX values!
  134. //
  135. fFirstChild.setValues(firstChild);
  136. if (secondChild != null) {
  137. fSecondChild.setValues(secondChild);
  138. }
  139. else {
  140. fSecondChild.clear();
  141. }
  142. fOperator = operator;
  143. }
  144. //
  145. // ContentModelValidator methods
  146. //
  147. /**
  148. * Check that the specified content is valid according to this
  149. * content model. This method can also be called to do 'what if'
  150. * testing of content models just to see if they would be valid.
  151. * <p>
  152. * A value of -1 in the children array indicates a PCDATA node. All other
  153. * indexes will be positive and represent child elements. The count can be
  154. * zero, since some elements have the EMPTY content model and that must be
  155. * confirmed.
  156. *
  157. * @param children The children of this element. Each integer is an index within
  158. * the <code>StringPool</code> of the child element name. An index
  159. * of -1 is used to indicate an occurrence of non-whitespace character
  160. * data.
  161. * @param offset Offset into the array where the children starts.
  162. * @param length The number of entries in the <code>children</code> array.
  163. *
  164. * @return The value -1 if fully valid, else the 0 based index of the child
  165. * that first failed. If the value returned is equal to the number
  166. * of children, then the specified children are valid but additional
  167. * content is required to reach a valid ending state.
  168. *
  169. */
  170. public int validate(QName[] children, int offset, int length) {
  171. //
  172. // According to the type of operation, we do the correct type of
  173. // content check.
  174. //
  175. switch(fOperator)
  176. {
  177. case XMLContentSpec.CONTENTSPECNODE_LEAF :
  178. // If there is not a child, then report an error at index 0
  179. if (length == 0)
  180. return 0;
  181. // If the 0th child is not the right kind, report an error at 0
  182. if (children[offset].rawname != fFirstChild.rawname) {
  183. return 0;
  184. }
  185. // If more than one child, report an error at index 1
  186. if (length > 1)
  187. return 1;
  188. break;
  189. case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE :
  190. //
  191. // If there is one child, make sure its the right type. If not,
  192. // then its an error at index 0.
  193. //
  194. if (length == 1) {
  195. if (children[offset].rawname != fFirstChild.rawname) {
  196. return 0;
  197. }
  198. }
  199. //
  200. // If the child count is greater than one, then obviously
  201. // bad, so report an error at index 1.
  202. //
  203. if (length > 1)
  204. return 1;
  205. break;
  206. case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE :
  207. //
  208. // If the child count is zero, that's fine. If its more than
  209. // zero, then make sure that all children are of the element
  210. // type that we stored. If not, report the index of the first
  211. // failed one.
  212. //
  213. if (length > 0)
  214. {
  215. for (int index = 0; index < length; index++) {
  216. if (children[offset + index].rawname != fFirstChild.rawname) {
  217. return index;
  218. }
  219. }
  220. }
  221. break;
  222. case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE :
  223. //
  224. // If the child count is zero, that's an error so report
  225. // an error at index 0.
  226. //
  227. if (length == 0)
  228. return 0;
  229. //
  230. // Otherwise we have to check them all to make sure that they
  231. // are of the correct child type. If not, then report the index
  232. // of the first one that is not.
  233. //
  234. for (int index = 0; index < length; index++) {
  235. if (children[offset + index].rawname != fFirstChild.rawname) {
  236. return index;
  237. }
  238. }
  239. break;
  240. case XMLContentSpec.CONTENTSPECNODE_CHOICE :
  241. //
  242. // There must be one and only one child, so if the element count
  243. // is zero, return an error at index 0.
  244. //
  245. if (length == 0)
  246. return 0;
  247. // If the zeroth element isn't one of our choices, error at 0
  248. if ((children[offset].rawname != fFirstChild.rawname) &&
  249. (children[offset].rawname != fSecondChild.rawname)) {
  250. return 0;
  251. }
  252. // If there is more than one element, then an error at 1
  253. if (length > 1)
  254. return 1;
  255. break;
  256. case XMLContentSpec.CONTENTSPECNODE_SEQ :
  257. //
  258. // There must be two children and they must be the two values
  259. // we stored, in the stored order.
  260. //
  261. if (length == 2) {
  262. if (children[offset].rawname != fFirstChild.rawname) {
  263. return 0;
  264. }
  265. if (children[offset + 1].rawname != fSecondChild.rawname) {
  266. return 1;
  267. }
  268. }
  269. else {
  270. if (length > 2) {
  271. return 2;
  272. }
  273. return length;
  274. }
  275. break;
  276. default :
  277. throw new RuntimeException("ImplementationMessages.VAL_CST");
  278. }
  279. // We survived, so return success status
  280. return -1;
  281. } // validate
  282. } // class SimpleContentModel