KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > dtd > models > SimpleContentModel


1 /*
2  * Copyright 1999-2002,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.impl.dtd.models;
18
19 import org.apache.xerces.xni.QName;
20
21 import org.apache.xerces.impl.dtd.XMLContentSpec;
22
23 /**
24  * SimpleContentModel is a derivative of the abstract content model base
25  * class that handles a small set of simple content models that are just
26  * way overkill to give the DFA treatment.
27  * <p>
28  * This class handles the following scenarios:
29  * <ul>
30  * <li> a
31  * <li> a?
32  * <li> a*
33  * <li> a+
34  * <li> a,b
35  * <li> a|b
36  * </ul>
37  * <p>
38  * These all involve a unary operation with one element type, or a binary
39  * operation with two elements. These are very simple and can be checked
40  * in a simple way without a DFA and without the overhead of setting up a
41  * DFA for such a simple check.
42  *
43  * @xerces.internal
44  *
45  * @version $Id: SimpleContentModel.java,v 1.7 2004/10/04 22:00:42 mrglavas Exp $
46  */

47 public class SimpleContentModel
48     implements ContentModelValidator {
49
50     //
51
// Constants
52
//
53

54     /** CHOICE */
55     public static final short CHOICE = -1;
56
57     /** SEQUENCE */
58     public static final short SEQUENCE = -1;
59
60     //
61
// Data
62
//
63

64
65     /**
66      * The element decl pool indices of the first (and optional second)
67      * child node. The operation code tells us whether the second child
68      * is used or not.
69      */

70     private QName fFirstChild = new QName();
71
72     /**
73      * The element decl pool indices of the first (and optional second)
74      * child node. The operation code tells us whether the second child
75      * is used or not.
76      */

77     private QName fSecondChild = new QName();
78
79     /**
80      * The operation that this object represents. Since this class only
81      * does simple contents, there is only ever a single operation
82      * involved (i.e. the children of the operation are always one or
83      * two leafs.) This is one of the XMLDTDParams.CONTENTSPECNODE_XXX values.
84      */

85     private int fOperator;
86
87     /* this is the EquivClassComparator object */
88     //private EquivClassComparator comparator = null;
89

90
91     //
92
// Constructors
93
//
94

95     /**
96      * Constructs a simple content model.
97      *
98      * @param operator The content model operator.
99      * @param firstChild qualified name of the first child
100      * @param secondChild qualified name of the second child
101      *
102      */

103     public SimpleContentModel(short operator, QName firstChild, QName secondChild) {
104         //
105
// Store away the children and operation. This is all we need to
106
// do the content model check.
107
//
108
// The operation is one of the ContentSpecNode.NODE_XXX values!
109
//
110
fFirstChild.setValues(firstChild);
111         if (secondChild != null) {
112             fSecondChild.setValues(secondChild);
113         }
114         else {
115             fSecondChild.clear();
116         }
117         fOperator = operator;
118     }
119
120     //
121
// ContentModelValidator methods
122
//
123

124     /**
125      * Check that the specified content is valid according to this
126      * content model. This method can also be called to do 'what if'
127      * testing of content models just to see if they would be valid.
128      * <p>
129      * A value of -1 in the children array indicates a PCDATA node. All other
130      * indexes will be positive and represent child elements. The count can be
131      * zero, since some elements have the EMPTY content model and that must be
132      * confirmed.
133      *
134      * @param children The children of this element. Each integer is an index within
135      * the <code>StringPool</code> of the child element name. An index
136      * of -1 is used to indicate an occurrence of non-whitespace character
137      * data.
138      * @param offset Offset into the array where the children starts.
139      * @param length The number of entries in the <code>children</code> array.
140      *
141      * @return The value -1 if fully valid, else the 0 based index of the child
142      * that first failed. If the value returned is equal to the number
143      * of children, then the specified children are valid but additional
144      * content is required to reach a valid ending state.
145      *
146      */

147     public int validate(QName[] children, int offset, int length) {
148
149         //
150
// According to the type of operation, we do the correct type of
151
// content check.
152
//
153
switch(fOperator)
154         {
155             case XMLContentSpec.CONTENTSPECNODE_LEAF :
156                 // If there is not a child, then report an error at index 0
157
if (length == 0)
158                     return 0;
159
160                 // If the 0th child is not the right kind, report an error at 0
161
if (children[offset].rawname != fFirstChild.rawname) {
162                     return 0;
163                 }
164
165                 // If more than one child, report an error at index 1
166
if (length > 1)
167                     return 1;
168                 break;
169
170             case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE :
171                 //
172
// If there is one child, make sure its the right type. If not,
173
// then its an error at index 0.
174
//
175
if (length == 1) {
176                     if (children[offset].rawname != fFirstChild.rawname) {
177                         return 0;
178                     }
179                 }
180
181                 //
182
// If the child count is greater than one, then obviously
183
// bad, so report an error at index 1.
184
//
185
if (length > 1)
186                     return 1;
187                 break;
188
189             case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE :
190                 //
191
// If the child count is zero, that's fine. If its more than
192
// zero, then make sure that all children are of the element
193
// type that we stored. If not, report the index of the first
194
// failed one.
195
//
196
if (length > 0)
197                 {
198                     for (int index = 0; index < length; index++) {
199                         if (children[offset + index].rawname != fFirstChild.rawname) {
200                             return index;
201                         }
202                     }
203                 }
204                 break;
205
206             case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE :
207                 //
208
// If the child count is zero, that's an error so report
209
// an error at index 0.
210
//
211
if (length == 0)
212                     return 0;
213
214                 //
215
// Otherwise we have to check them all to make sure that they
216
// are of the correct child type. If not, then report the index
217
// of the first one that is not.
218
//
219
for (int index = 0; index < length; index++) {
220                     if (children[offset + index].rawname != fFirstChild.rawname) {
221                         return index;
222                     }
223                 }
224                 break;
225
226             case XMLContentSpec.CONTENTSPECNODE_CHOICE :
227                 //
228
// There must be one and only one child, so if the element count
229
// is zero, return an error at index 0.
230
//
231
if (length == 0)
232                     return 0;
233
234                 // If the zeroth element isn't one of our choices, error at 0
235
if ((children[offset].rawname != fFirstChild.rawname) &&
236                     (children[offset].rawname != fSecondChild.rawname)) {
237                     return 0;
238                 }
239
240                 // If there is more than one element, then an error at 1
241
if (length > 1)
242                     return 1;
243                 break;
244
245             case XMLContentSpec.CONTENTSPECNODE_SEQ :
246                 //
247
// There must be two children and they must be the two values
248
// we stored, in the stored order.
249
//
250
if (length == 2) {
251                     if (children[offset].rawname != fFirstChild.rawname) {
252                         return 0;
253                     }
254                     if (children[offset + 1].rawname != fSecondChild.rawname) {
255                         return 1;
256                     }
257                 }
258                 else {
259                     if (length > 2) {
260                         return 2;
261                     }
262
263                     return length;
264                 }
265
266                 break;
267
268             default :
269                 throw new RuntimeException JavaDoc("ImplementationMessages.VAL_CST");
270         }
271
272         // We survived, so return success status
273
return -1;
274     } // validate
275

276 } // class SimpleContentModel
277
Popular Tags