KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > event > StartTagBuffer


1 package net.sf.saxon.event;
2 import net.sf.saxon.om.AttributeCollectionImpl;
3 import net.sf.saxon.om.NamePool;
4 import net.sf.saxon.om.NamespaceConstant;
5 import net.sf.saxon.om.NamespaceResolver;
6 import net.sf.saxon.trans.XPathException;
7
8 import java.util.ArrayList JavaDoc;
9 import java.util.Iterator JavaDoc;
10 import java.util.List JavaDoc;
11
12 /**
13   * StartTagBuffer is a ProxyReceiver that buffers attributes and namespace events within a start tag.
14   * It maintains details of the namespace context, and a full set of attribute information, on behalf
15   * of other filters that need access to namespace information or need to process attributes in arbitrary
16   * order.
17   */

18
19 public class StartTagBuffer extends ProxyReceiver implements NamespaceResolver
20 {
21
22     // Details of the pending element event
23

24     int elementNameCode;
25     int elementTypeCode;
26     int elementLocationId;
27     int elementProperties;
28
29     // Details of pending attribute events
30

31     AttributeCollectionImpl bufferedAttributes;
32
33     // We keep track of namespaces. The namespaces
34
// vector holds a list of all namespaces currently declared (organised as pairs of entries,
35
// prefix followed by URI). The stack contains an entry for each element currently open; the
36
// value on the stack is an Integer giving the number of namespaces added to the main
37
// namespace stack by that element.
38

39     private int[] namespaces = new int[50]; // all namespace codes currently declared
40
private int namespacesSize = 0; // all namespaces currently declared
41
private int[] countStack = new int[50];
42     private int depth = 0;
43
44     // TODO: support namespace undeclarations
45

46     public void setPipelineConfiguration(PipelineConfiguration config) {
47         super.setPipelineConfiguration(config);
48         bufferedAttributes = new AttributeCollectionImpl(getNamePool());
49     }
50
51     /**
52     * startElement
53     */

54
55     public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException {
56
57         elementNameCode = nameCode;
58         elementTypeCode = typeCode;
59         elementLocationId = locationId;
60         elementProperties = properties;
61
62         bufferedAttributes.clear();
63
64         // Record the current height of the namespace list so it can be reset at endElement time
65

66         countStack[depth] = 0;
67         if (++depth >= countStack.length) {
68             int[] newstack = new int[depth*2];
69             System.arraycopy(countStack, 0, newstack, 0, depth);
70             countStack = newstack;
71         }
72     }
73
74     public void namespace(int namespaceCode, int properties) throws XPathException {
75         addToStack(namespaceCode);
76         countStack[depth - 1]++;
77     }
78
79     /**
80      * Notify an attribute. Attributes are notified after the startElement event, and before any
81      * children. Namespaces and attributes may be intermingled.
82      *
83      * @param nameCode The name of the attribute, as held in the name pool
84      * @param typeCode The type of the attribute, as held in the name pool
85      * @param properties Bit significant value. The following bits are defined:
86      * <dd>DISABLE_ESCAPING</dd> <dt>Disable escaping for this attribute</dt>
87      * <dd>NO_SPECIAL_CHARACTERS</dd> <dt>Attribute value contains no special characters</dt>
88      * @throws IllegalStateException: attempt to output an attribute when there is no open element
89      * start tag
90      */

91
92     public void attribute(int nameCode, int typeCode, CharSequence JavaDoc value, int locationId, int properties) throws XPathException {
93         bufferedAttributes.addAttribute(nameCode, typeCode, value.toString(), locationId, properties);
94     }
95
96     /**
97     * Add a namespace declaration to the stack
98     */

99
100     private void addToStack(int nscode) {
101         // expand the stack if necessary
102
if (namespacesSize+1 >= namespaces.length) {
103             int[] newlist = new int[namespacesSize*2];
104             System.arraycopy(namespaces, 0, newlist, 0, namespacesSize);
105             namespaces = newlist;
106         }
107         namespaces[namespacesSize++] = nscode;
108     }
109
110     /**
111      * startContent: Add any namespace undeclarations needed to stop
112      * namespaces being inherited from parent elements
113      */

114
115     public void startContent() throws XPathException {
116         super.startElement(elementNameCode, elementTypeCode, elementLocationId, elementProperties);
117         declareNamespacesForStartElement();
118
119         for (int i=0; i<bufferedAttributes.getLength(); i++) {
120             super.attribute(bufferedAttributes.getNameCode(i),
121                     bufferedAttributes.getTypeAnnotation(i),
122                     bufferedAttributes.getValue(i),
123                     bufferedAttributes.getLocationId(i),
124                     bufferedAttributes.getProperties(i));
125         }
126         super.startContent();
127     }
128
129     protected void declareNamespacesForStartElement() throws XPathException {
130         for (int i=namespacesSize - countStack[depth-1]; i<namespacesSize; i++) {
131             super.namespace(namespaces[i], 0);
132         }
133     }
134
135     protected void declareAllNamespaces() throws XPathException {
136         for (int i=0; i<namespacesSize; i++) {
137             super.namespace(namespaces[i], 0);
138         }
139     }
140
141     /**
142     * endElement: Discard the namespaces declared on this element.
143     */

144
145     public void endElement () throws XPathException {
146         super.endElement();
147         undeclareNamespacesForElement();
148     }
149
150     protected void undeclareNamespacesForElement() {
151         int nscount = countStack[--depth];
152         namespacesSize -= nscount;
153     }
154
155     /**
156      * Get the name of the current element
157      */

158
159     public int getElementNameCode() {
160         return elementNameCode;
161     }
162
163     /**
164      * Get the value of the current attribute with a given nameCode
165      * @return the attribute value, or null if the attribute is not present
166      */

167
168     public String JavaDoc getAttribute(int nameCode) {
169         return bufferedAttributes.getValueByFingerprint(nameCode & 0xfffff);
170     }
171
172     /**
173      * Get the URI code corresponding to a given prefix code, by searching the
174      * in-scope namespaces. This is a service provided to subclasses.
175      * @param prefixCode the 16-bit prefix code required
176      * @return the 16-bit URI code, or -1 if the prefix is not found
177      */

178
179     protected short getURICode(short prefixCode) {
180         for (int i=namespacesSize-1; i>=0; i--) {
181             if ((namespaces[i]>>16) == (prefixCode)) {
182                 return (short)(namespaces[i]&0xffff);
183             }
184         }
185         if (prefixCode == 0) {
186             return 0; // by default, no prefix means no namespace URI
187
} else {
188             return -1;
189         }
190     }
191
192     /**
193      * Get the namespace URI corresponding to a given prefix. Return null
194      * if the prefix is not in scope.
195      *
196      * @param prefix the namespace prefix
197      * @param useDefault true if the default namespace is to be used when the
198      * prefix is ""
199      * @return the uri for the namespace, or null if the prefix is not in scope
200      */

201
202     public String JavaDoc getURIForPrefix(String JavaDoc prefix, boolean useDefault) {
203         NamePool pool = getNamePool();
204         if ("".equals(prefix) && !useDefault) {
205             return "";
206         } else if ("xml".equals(prefix)) {
207             return NamespaceConstant.XML;
208         } else {
209             short prefixCode = pool.getCodeForPrefix(prefix);
210             short uriCode = getURICode(prefixCode);
211             if (uriCode == -1) {
212                 return null;
213             }
214             return pool.getURIFromURICode(uriCode);
215         }
216     }
217
218     /**
219      * Get an iterator over all the prefixes declared in this namespace context. This will include
220      * the default namespace (prefix="") and the XML namespace where appropriate
221      */

222
223     public Iterator JavaDoc iteratePrefixes() {
224         NamePool pool = getNamePool();
225         List JavaDoc prefixes = new ArrayList JavaDoc(namespacesSize);
226         for (int i=namespacesSize-1; i>=0; i--) {
227             String JavaDoc prefix = pool.getPrefixFromNamespaceCode(namespaces[i]);
228             if (!prefixes.contains(prefix)) {
229                 prefixes.add(prefix);
230             }
231         }
232         prefixes.add("xml");
233         return prefixes.iterator();
234     }
235 }
236
237 //
238
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
239
// you may not use this file except in compliance with the License. You may obtain a copy of the
240
// License at http://www.mozilla.org/MPL/
241
//
242
// Software distributed under the License is distributed on an "AS IS" basis,
243
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
244
// See the License for the specific language governing rights and limitations under the License.
245
//
246
// The Original Code is: all this file.
247
//
248
// The Initial Developer of the Original Code is Michael H. Kay.
249
//
250
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
251
//
252
// Contributor(s): none.
253
//
254
Popular Tags