~ubuntu-branches/ubuntu/karmic/libxerces2-java/karmic

« back to all changes in this revision

Viewing changes to src/org/apache/xerces/impl/dtd/BalancedDTDGrammar.java

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2006-12-04 17:37:55 UTC
  • mfrom: (2.1.2 etch)
  • Revision ID: james.westby@ubuntu.com-20061204173755-hb6ybrrrk097zhx7
Tags: 2.8.1-1ubuntu1
* Merge with Debian unstable; remaining changes:
  - Build -gcj package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2005 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;
 
18
 
 
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;
 
23
 
 
24
/**
 
25
 * <p>A DTD grammar that produces balanced syntax trees.</p>
 
26
 * 
 
27
 * @xerces.internal
 
28
 * 
 
29
 * @author Michael Glavassevich, IBM
 
30
 * @version $Id: BalancedDTDGrammar.java 349355 2005-11-28 03:56:09Z mrglavas $
 
31
 */
 
32
final class BalancedDTDGrammar extends DTDGrammar {
 
33
    
 
34
    //
 
35
    // Data
 
36
    //
 
37
    
 
38
    /** Mixed. */
 
39
    private boolean fMixed;
 
40
    
 
41
    /** Stack depth */
 
42
    private int fDepth = 0;
 
43
    
 
44
    /** Children content model operation stack. */
 
45
    private short [] fOpStack = null;
 
46
    
 
47
    /** Holder for choice/sequence/leaf groups at each depth. */
 
48
    private int [][] fGroupIndexStack;
 
49
    
 
50
    /** Sizes of the allocated portions of each int[] in fGroupIndexStack. */
 
51
    private int [] fGroupIndexStackSizes;
 
52
    
 
53
    //
 
54
    // Constructors
 
55
    //
 
56
 
 
57
    /** Default constructor. */
 
58
    public BalancedDTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) {
 
59
        super(symbolTable, desc);
 
60
    } // BalancedDTDGrammar(SymbolTable,XMLDTDDescription)
 
61
    
 
62
    //
 
63
    // Public methods
 
64
    //
 
65
    
 
66
    /**
 
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.
 
70
     *
 
71
     * @param elementName The name of the element.
 
72
     * @param augs Additional information that may include infoset
 
73
     *                      augmentations.
 
74
     * @throws XNIException Thrown by handler to signal an error.
 
75
     */
 
76
    public final void startContentModel(String elementName, Augmentations augs)
 
77
        throws XNIException {
 
78
        fDepth = 0;
 
79
        initializeContentModelStacks();
 
80
        super.startContentModel(elementName, augs);
 
81
    } // startContentModel(String)
 
82
    
 
83
    /**
 
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.
 
88
     *
 
89
     * @param augs Additional information that may include infoset
 
90
     *                      augmentations.
 
91
     * @throws XNIException Thrown by handler to signal an error.
 
92
     *
 
93
     * @see #any
 
94
     * @see #empty
 
95
     */
 
96
    public final void startGroup(Augmentations augs) throws XNIException {
 
97
        ++fDepth;
 
98
        initializeContentModelStacks();
 
99
        fMixed = false;
 
100
    } // startGroup()
 
101
    
 
102
    /**
 
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>.
 
106
     *
 
107
     *@param augs Additional information that may include infoset
 
108
     *                      augmentations.
 
109
     *
 
110
     * @throws XNIException Thrown by handler to signal an error.
 
111
     *
 
112
     * @see #startGroup
 
113
     */
 
114
    public final void pcdata(Augmentations augs) throws XNIException {
 
115
        fMixed = true;
 
116
    } // pcdata()
 
117
 
 
118
    /**
 
119
     * A referenced element in a mixed or children content model.
 
120
     *
 
121
     * @param elementName The name of the referenced element.
 
122
     * @param augs Additional information that may include infoset
 
123
     *                      augmentations.
 
124
     *
 
125
     * @throws XNIException Thrown by handler to signal an error.
 
126
     */
 
127
    public final void element(String elementName, Augmentations augs) throws XNIException {
 
128
        addToCurrentGroup(addUniqueLeafNode(elementName));
 
129
    } // element(String)
 
130
 
 
131
    /**
 
132
     * The separator between choices or sequences of a mixed or children
 
133
     * content model.
 
134
     *
 
135
     * @param separator The type of children separator.
 
136
     * @param augs Additional information that may include infoset
 
137
     *                      augmentations.
 
138
     * @throws XNIException Thrown by handler to signal an error.
 
139
     *
 
140
     * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE
 
141
     * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE
 
142
     */
 
143
    public final void separator(short separator, Augmentations augs) throws XNIException {
 
144
        if (separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE) {
 
145
            fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
 
146
        }
 
147
        else if (separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) {
 
148
            fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
 
149
        }
 
150
    } // separator(short)
 
151
 
 
152
    /**
 
153
     * The occurrence count for a child in a children content model or
 
154
     * for the mixed content model group.
 
155
     *
 
156
     * @param occurrence The occurrence count for the last element
 
157
     *                   or group.
 
158
     * @param augs Additional information that may include infoset
 
159
     *                      augmentations.
 
160
     * @throws XNIException Thrown by handler to signal an error.
 
161
     *
 
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
 
165
     */
 
166
    public final void occurrence(short occurrence, Augmentations augs) throws XNIException {
 
167
        if (!fMixed) {
 
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);
 
171
            } 
 
172
            else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE) {
 
173
                fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1);
 
174
            } 
 
175
            else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) {
 
176
                fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1);
 
177
            }
 
178
        }
 
179
    } // occurrence(short)
 
180
 
 
181
    /**
 
182
     * The end of a group for mixed or children content models.
 
183
     *
 
184
     * @param augs Additional information that may include infoset
 
185
     *                      augmentations.
 
186
     * @throws XNIException Thrown by handler to signal an error.
 
187
     */
 
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);
 
191
        --fDepth;
 
192
        addToCurrentGroup(group);
 
193
    } // endGroup()
 
194
    
 
195
    /**
 
196
     * The end of the DTD.
 
197
     *
 
198
     * @param augs Additional information that may include infoset
 
199
     *                      augmentations.
 
200
     * @throws XNIException Thrown by handler to signal an error.
 
201
     */
 
202
    public final void endDTD(Augmentations augs) throws XNIException {
 
203
        super.endDTD(augs);
 
204
        fOpStack = null;
 
205
        fGroupIndexStack = null;
 
206
        fGroupIndexStackSizes = null;
 
207
    } // endDTD()
 
208
    
 
209
    //
 
210
    // Protected methods
 
211
    //
 
212
    
 
213
    /**
 
214
     * Adds the content spec to the given element declaration.
 
215
     */
 
216
    protected final void addContentSpecToElement(XMLElementDecl elementDecl) {
 
217
        int contentSpec = fGroupIndexStackSizes[0] > 0 ? fGroupIndexStack[0][0] : -1;
 
218
        setContentSpecIndex(fCurrentElementIndex, contentSpec);
 
219
    }
 
220
    
 
221
    //
 
222
    // Private methods
 
223
    //
 
224
    
 
225
    /**
 
226
     * Creates a subtree from the leaf nodes at the current depth.
 
227
     */
 
228
    private int addContentSpecNodes(int begin, int end) {
 
229
        if (begin == end) {
 
230
            return fGroupIndexStack[fDepth][begin];
 
231
        }
 
232
        int middle = (begin + end) / 2;
 
233
        return addContentSpecNode(fOpStack[fDepth], 
 
234
                addContentSpecNodes(begin, middle), 
 
235
                addContentSpecNodes(middle + 1, end));
 
236
    } // addContentSpecNodes(int,int)
 
237
    
 
238
    /**
 
239
     * Initialize the stacks which temporarily hold content models.
 
240
     */
 
241
    private void initializeContentModelStacks() {
 
242
        if (fOpStack == null) {
 
243
            fOpStack = new short[8];
 
244
            fGroupIndexStack = new int [8][];
 
245
            fGroupIndexStackSizes = new int [8];
 
246
        }
 
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;
 
257
        }
 
258
        fOpStack[fDepth] = -1;
 
259
        fGroupIndexStackSizes[fDepth] = 0;
 
260
    } // initializeContentModelStacks()
 
261
    
 
262
    /**
 
263
     * Add XMLContentSpec to the current group.
 
264
     * 
 
265
     * @param contentSpec handle to the XMLContentSpec to add to the current group
 
266
     */
 
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;
 
273
        }
 
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;
 
279
        }
 
280
        currentGroup[length] = contentSpec;
 
281
    } // addToCurrentGroup(int)
 
282
 
 
283
} // class BalancedDTDGrammar