2
* Copyright 2005 The Apache Software Foundation.
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
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
17
package org.apache.xerces.impl.dtd;
19
import org.apache.xerces.util.SymbolTable;
20
import org.apache.xerces.xni.Augmentations;
21
import org.apache.xerces.xni.XMLDTDContentModelHandler;
22
import org.apache.xerces.xni.XNIException;
25
* <p>A DTD grammar that produces balanced syntax trees.</p>
29
* @author Michael Glavassevich, IBM
30
* @version $Id: BalancedDTDGrammar.java 349355 2005-11-28 03:56:09Z mrglavas $
32
final class BalancedDTDGrammar extends DTDGrammar {
39
private boolean fMixed;
42
private int fDepth = 0;
44
/** Children content model operation stack. */
45
private short [] fOpStack = null;
47
/** Holder for choice/sequence/leaf groups at each depth. */
48
private int [][] fGroupIndexStack;
50
/** Sizes of the allocated portions of each int[] in fGroupIndexStack. */
51
private int [] fGroupIndexStackSizes;
57
/** Default constructor. */
58
public BalancedDTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) {
59
super(symbolTable, desc);
60
} // BalancedDTDGrammar(SymbolTable,XMLDTDDescription)
67
* The start of a content model. Depending on the type of the content
68
* model, specific methods may be called between the call to the
69
* startContentModel method and the call to the endContentModel method.
71
* @param elementName The name of the element.
72
* @param augs Additional information that may include infoset
74
* @throws XNIException Thrown by handler to signal an error.
76
public final void startContentModel(String elementName, Augmentations augs)
79
initializeContentModelStacks();
80
super.startContentModel(elementName, augs);
81
} // startContentModel(String)
84
* A start of either a mixed or children content model. A mixed
85
* content model will immediately be followed by a call to the
86
* <code>pcdata()</code> method. A children content model will
87
* contain additional groups and/or elements.
89
* @param augs Additional information that may include infoset
91
* @throws XNIException Thrown by handler to signal an error.
96
public final void startGroup(Augmentations augs) throws XNIException {
98
initializeContentModelStacks();
103
* The appearance of "#PCDATA" within a group signifying a
104
* mixed content model. This method will be the first called
105
* following the content model's <code>startGroup()</code>.
107
*@param augs Additional information that may include infoset
110
* @throws XNIException Thrown by handler to signal an error.
114
public final void pcdata(Augmentations augs) throws XNIException {
119
* A referenced element in a mixed or children content model.
121
* @param elementName The name of the referenced element.
122
* @param augs Additional information that may include infoset
125
* @throws XNIException Thrown by handler to signal an error.
127
public final void element(String elementName, Augmentations augs) throws XNIException {
128
addToCurrentGroup(addUniqueLeafNode(elementName));
132
* The separator between choices or sequences of a mixed or children
135
* @param separator The type of children separator.
136
* @param augs Additional information that may include infoset
138
* @throws XNIException Thrown by handler to signal an error.
140
* @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE
141
* @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE
143
public final void separator(short separator, Augmentations augs) throws XNIException {
144
if (separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE) {
145
fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
147
else if (separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) {
148
fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
150
} // separator(short)
153
* The occurrence count for a child in a children content model or
154
* for the mixed content model group.
156
* @param occurrence The occurrence count for the last element
158
* @param augs Additional information that may include infoset
160
* @throws XNIException Thrown by handler to signal an error.
162
* @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE
163
* @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE
164
* @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE
166
public final void occurrence(short occurrence, Augmentations augs) throws XNIException {
168
int currentIndex = fGroupIndexStackSizes[fDepth] - 1;
169
if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE) {
170
fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fGroupIndexStack[fDepth][currentIndex], -1);
172
else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE) {
173
fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1);
175
else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) {
176
fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1);
179
} // occurrence(short)
182
* The end of a group for mixed or children content models.
184
* @param augs Additional information that may include infoset
186
* @throws XNIException Thrown by handler to signal an error.
188
public final void endGroup(Augmentations augs) throws XNIException {
189
final int length = fGroupIndexStackSizes[fDepth];
190
final int group = length > 0 ? addContentSpecNodes(0, length - 1) : addUniqueLeafNode(null);
192
addToCurrentGroup(group);
196
* The end of the DTD.
198
* @param augs Additional information that may include infoset
200
* @throws XNIException Thrown by handler to signal an error.
202
public final void endDTD(Augmentations augs) throws XNIException {
205
fGroupIndexStack = null;
206
fGroupIndexStackSizes = null;
214
* Adds the content spec to the given element declaration.
216
protected final void addContentSpecToElement(XMLElementDecl elementDecl) {
217
int contentSpec = fGroupIndexStackSizes[0] > 0 ? fGroupIndexStack[0][0] : -1;
218
setContentSpecIndex(fCurrentElementIndex, contentSpec);
226
* Creates a subtree from the leaf nodes at the current depth.
228
private int addContentSpecNodes(int begin, int end) {
230
return fGroupIndexStack[fDepth][begin];
232
int middle = (begin + end) / 2;
233
return addContentSpecNode(fOpStack[fDepth],
234
addContentSpecNodes(begin, middle),
235
addContentSpecNodes(middle + 1, end));
236
} // addContentSpecNodes(int,int)
239
* Initialize the stacks which temporarily hold content models.
241
private void initializeContentModelStacks() {
242
if (fOpStack == null) {
243
fOpStack = new short[8];
244
fGroupIndexStack = new int [8][];
245
fGroupIndexStackSizes = new int [8];
247
else if (fDepth == fOpStack.length) {
248
short [] newOpStack = new short[fDepth * 2];
249
System.arraycopy(fOpStack, 0, newOpStack, 0, fDepth);
250
fOpStack = newOpStack;
251
int [][] newGroupIndexStack = new int[fDepth * 2][];
252
System.arraycopy(fGroupIndexStack, 0, newGroupIndexStack, 0, fDepth);
253
fGroupIndexStack = newGroupIndexStack;
254
int [] newGroupIndexStackLengths = new int[fDepth * 2];
255
System.arraycopy(fGroupIndexStackSizes, 0, newGroupIndexStackLengths, 0, fDepth);
256
fGroupIndexStackSizes = newGroupIndexStackLengths;
258
fOpStack[fDepth] = -1;
259
fGroupIndexStackSizes[fDepth] = 0;
260
} // initializeContentModelStacks()
263
* Add XMLContentSpec to the current group.
265
* @param contentSpec handle to the XMLContentSpec to add to the current group
267
private void addToCurrentGroup(int contentSpec) {
268
int [] currentGroup = fGroupIndexStack[fDepth];
269
int length = fGroupIndexStackSizes[fDepth]++;
270
if (currentGroup == null) {
271
currentGroup = new int[8];
272
fGroupIndexStack[fDepth] = currentGroup;
274
else if (length == currentGroup.length) {
275
int [] newGroup = new int[currentGroup.length * 2];
276
System.arraycopy(currentGroup, 0, newGroup, 0, currentGroup.length);
277
currentGroup = newGroup;
278
fGroupIndexStack[fDepth] = currentGroup;
280
currentGroup[length] = contentSpec;
281
} // addToCurrentGroup(int)
283
} // class BalancedDTDGrammar