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