author | joehw |
Wed, 18 Oct 2017 13:25:49 -0700 | |
changeset 47359 | e1a6c0168741 |
parent 47216 | 71c04702a3d5 |
child 48409 | 5ab69533994b |
permissions | -rw-r--r-- |
6 | 1 |
/* |
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
2 |
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. |
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
3 |
* @LastModified: Oct 2017 |
6 | 4 |
*/ |
5 |
/* |
|
44797
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
6 |
* Licensed to the Apache Software Foundation (ASF) under one or more |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
7 |
* contributor license agreements. See the NOTICE file distributed with |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
8 |
* this work for additional information regarding copyright ownership. |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
9 |
* The ASF licenses this file to You under the Apache License, Version 2.0 |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
10 |
* (the "License"); you may not use this file except in compliance with |
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
11 |
* the License. You may obtain a copy of the License at |
6 | 12 |
* |
44797
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
13 |
* http://www.apache.org/licenses/LICENSE-2.0 |
6 | 14 |
* |
15 |
* Unless required by applicable law or agreed to in writing, software |
|
16 |
* distributed under the License is distributed on an "AS IS" BASIS, |
|
17 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
18 |
* See the License for the specific language governing permissions and |
|
19 |
* limitations under the License. |
|
20 |
*/ |
|
44797
8b3b3b911b8a
8162572: Update License Header for all JAXP sources
joehw
parents:
25868
diff
changeset
|
21 |
|
6 | 22 |
package com.sun.org.apache.xml.internal.dtm.ref; |
23 |
||
24 |
import com.sun.org.apache.xml.internal.dtm.*; |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
25 |
import com.sun.org.apache.xml.internal.res.XMLErrorResources; |
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
26 |
import com.sun.org.apache.xml.internal.res.XMLMessages; |
6 | 27 |
import com.sun.org.apache.xml.internal.utils.BoolStack; |
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
28 |
import com.sun.org.apache.xml.internal.utils.SuballocatedIntVector; |
6 | 29 |
import com.sun.org.apache.xml.internal.utils.XMLString; |
30 |
import com.sun.org.apache.xml.internal.utils.XMLStringFactory; |
|
31 |
import java.io.*; // for dumpDTM |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
32 |
import java.util.Vector; |
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
33 |
import javax.xml.transform.Source; |
6 | 34 |
|
35 |
/** |
|
36 |
* The <code>DTMDefaultBase</code> class serves as a helper base for DTMs. |
|
37 |
* It sets up structures for navigation and type, while leaving data |
|
38 |
* management and construction to the derived classes. |
|
39 |
*/ |
|
40 |
public abstract class DTMDefaultBase implements DTM |
|
41 |
{ |
|
42 |
static final boolean JJK_DEBUG=false; |
|
43 |
||
44 |
// This constant is likely to be removed in the future. Use the |
|
45 |
// getDocument() method instead of ROOTNODE to get at the root |
|
46 |
// node of a DTM. |
|
47 |
/** The identity of the root node. */ |
|
48 |
public static final int ROOTNODE = 0; |
|
49 |
||
50 |
/** |
|
51 |
* The number of nodes, which is also used to determine the next |
|
52 |
* node index. |
|
53 |
*/ |
|
54 |
protected int m_size = 0; |
|
55 |
||
56 |
/** The expanded names, one array element for each node. */ |
|
57 |
protected SuballocatedIntVector m_exptype; |
|
58 |
||
59 |
/** First child values, one array element for each node. */ |
|
60 |
protected SuballocatedIntVector m_firstch; |
|
61 |
||
62 |
/** Next sibling values, one array element for each node. */ |
|
63 |
protected SuballocatedIntVector m_nextsib; |
|
64 |
||
65 |
/** Previous sibling values, one array element for each node. */ |
|
66 |
protected SuballocatedIntVector m_prevsib; |
|
67 |
||
68 |
/** Previous sibling values, one array element for each node. */ |
|
69 |
protected SuballocatedIntVector m_parent; |
|
70 |
||
71 |
/** Vector of SuballocatedIntVectors of NS decl sets */ |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
72 |
protected Vector<SuballocatedIntVector> m_namespaceDeclSets = null; |
6 | 73 |
|
74 |
/** SuballocatedIntVector of elements at which corresponding |
|
75 |
* namespaceDeclSets were defined */ |
|
76 |
protected SuballocatedIntVector m_namespaceDeclSetElements = null; |
|
77 |
||
78 |
/** |
|
79 |
* These hold indexes to elements based on namespace and local name. |
|
80 |
* The base lookup is the the namespace. The second lookup is the local |
|
81 |
* name, and the last array contains the the first free element |
|
82 |
* at the start, and the list of element handles following. |
|
83 |
*/ |
|
84 |
protected int[][][] m_elemIndexes; |
|
85 |
||
86 |
/** The default block size of the node arrays */ |
|
87 |
public static final int DEFAULT_BLOCKSIZE = 512; // favor small docs. |
|
88 |
||
89 |
/** The number of blocks for the node arrays */ |
|
90 |
public static final int DEFAULT_NUMBLOCKS = 32; |
|
91 |
||
92 |
/** The number of blocks used for small documents & RTFs */ |
|
93 |
public static final int DEFAULT_NUMBLOCKS_SMALL = 4; |
|
94 |
||
95 |
/** The block size of the node arrays */ |
|
96 |
//protected final int m_blocksize; |
|
97 |
||
98 |
/** |
|
99 |
* The value to use when the information has not been built yet. |
|
100 |
*/ |
|
101 |
protected static final int NOTPROCESSED = DTM.NULL - 1; |
|
102 |
||
103 |
/** |
|
104 |
* The DTM manager who "owns" this DTM. |
|
105 |
*/ |
|
106 |
||
107 |
public DTMManager m_mgr; |
|
108 |
||
109 |
/** |
|
110 |
* m_mgr cast to DTMManagerDefault, or null if it isn't an instance |
|
111 |
* (Efficiency hook) |
|
112 |
*/ |
|
113 |
protected DTMManagerDefault m_mgrDefault=null; |
|
114 |
||
115 |
||
116 |
/** The document identity number(s). If we have overflowed the addressing |
|
117 |
* range of the first that was assigned to us, we may add others. */ |
|
118 |
protected SuballocatedIntVector m_dtmIdent; |
|
119 |
||
120 |
/** The mask for the identity. |
|
121 |
%REVIEW% Should this really be set to the _DEFAULT? What if |
|
122 |
a particular DTM wanted to use another value? */ |
|
123 |
//protected final static int m_mask = DTMManager.IDENT_NODE_DEFAULT; |
|
124 |
||
125 |
/** The base URI for this document. */ |
|
126 |
protected String m_documentBaseURI; |
|
127 |
||
128 |
/** |
|
129 |
* The whitespace filter that enables elements to strip whitespace or not. |
|
130 |
*/ |
|
131 |
protected DTMWSFilter m_wsfilter; |
|
132 |
||
133 |
/** Flag indicating whether to strip whitespace nodes */ |
|
134 |
protected boolean m_shouldStripWS = false; |
|
135 |
||
136 |
/** Stack of flags indicating whether to strip whitespace nodes */ |
|
137 |
protected BoolStack m_shouldStripWhitespaceStack; |
|
138 |
||
139 |
/** The XMLString factory for creating XMLStrings. */ |
|
140 |
protected XMLStringFactory m_xstrf; |
|
141 |
||
142 |
/** |
|
143 |
* The table for exandedNameID lookups. This may or may not be the same |
|
144 |
* table as is contained in the DTMManagerDefault. |
|
145 |
*/ |
|
146 |
protected ExpandedNameTable m_expandedNameTable; |
|
147 |
||
148 |
/** true if indexing is turned on. */ |
|
149 |
protected boolean m_indexing; |
|
150 |
||
151 |
/** |
|
152 |
* Construct a DTMDefaultBase object using the default block size. |
|
153 |
* |
|
154 |
* @param mgr The DTMManager who owns this DTM. |
|
155 |
* @param source The object that is used to specify the construction source. |
|
156 |
* @param dtmIdentity The DTM identity ID for this DTM. |
|
157 |
* @param whiteSpaceFilter The white space filter for this DTM, which may |
|
158 |
* be null. |
|
159 |
* @param xstringfactory The factory to use for creating XMLStrings. |
|
160 |
* @param doIndexing true if the caller considers it worth it to use |
|
161 |
* indexing schemes. |
|
162 |
*/ |
|
163 |
public DTMDefaultBase(DTMManager mgr, Source source, int dtmIdentity, |
|
164 |
DTMWSFilter whiteSpaceFilter, |
|
165 |
XMLStringFactory xstringfactory, boolean doIndexing) |
|
166 |
{ |
|
167 |
this(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory, |
|
168 |
doIndexing, DEFAULT_BLOCKSIZE, true, false); |
|
169 |
} |
|
170 |
||
171 |
/** |
|
172 |
* Construct a DTMDefaultBase object from a DOM node. |
|
173 |
* |
|
174 |
* @param mgr The DTMManager who owns this DTM. |
|
175 |
* @param source The object that is used to specify the construction source. |
|
176 |
* @param dtmIdentity The DTM identity ID for this DTM. |
|
177 |
* @param whiteSpaceFilter The white space filter for this DTM, which may |
|
178 |
* be null. |
|
179 |
* @param xstringfactory The factory to use for creating XMLStrings. |
|
180 |
* @param doIndexing true if the caller considers it worth it to use |
|
181 |
* indexing schemes. |
|
182 |
* @param blocksize The block size of the DTM. |
|
183 |
* @param usePrevsib true if we want to build the previous sibling node array. |
|
184 |
* @param newNameTable true if we want to use a new ExpandedNameTable for this DTM. |
|
185 |
*/ |
|
186 |
public DTMDefaultBase(DTMManager mgr, Source source, int dtmIdentity, |
|
187 |
DTMWSFilter whiteSpaceFilter, |
|
188 |
XMLStringFactory xstringfactory, boolean doIndexing, |
|
189 |
int blocksize, boolean usePrevsib, |
|
190 |
boolean newNameTable) |
|
191 |
{ |
|
192 |
// Use smaller sizes for the internal node arrays if the block size |
|
193 |
// is small. |
|
194 |
int numblocks; |
|
195 |
if (blocksize <= 64) |
|
196 |
{ |
|
197 |
numblocks = DEFAULT_NUMBLOCKS_SMALL; |
|
198 |
m_dtmIdent= new SuballocatedIntVector(4, 1); |
|
199 |
} |
|
200 |
else |
|
201 |
{ |
|
202 |
numblocks = DEFAULT_NUMBLOCKS; |
|
203 |
m_dtmIdent= new SuballocatedIntVector(32); |
|
204 |
} |
|
205 |
||
206 |
m_exptype = new SuballocatedIntVector(blocksize, numblocks); |
|
207 |
m_firstch = new SuballocatedIntVector(blocksize, numblocks); |
|
208 |
m_nextsib = new SuballocatedIntVector(blocksize, numblocks); |
|
209 |
m_parent = new SuballocatedIntVector(blocksize, numblocks); |
|
210 |
||
211 |
// Only create the m_prevsib array if the usePrevsib flag is true. |
|
212 |
// Some DTM implementations (e.g. SAXImpl) do not need this array. |
|
213 |
// We can save the time to build it in those cases. |
|
214 |
if (usePrevsib) |
|
215 |
m_prevsib = new SuballocatedIntVector(blocksize, numblocks); |
|
216 |
||
217 |
m_mgr = mgr; |
|
218 |
if(mgr instanceof DTMManagerDefault) |
|
219 |
m_mgrDefault=(DTMManagerDefault)mgr; |
|
220 |
||
221 |
m_documentBaseURI = (null != source) ? source.getSystemId() : null; |
|
222 |
m_dtmIdent.setElementAt(dtmIdentity,0); |
|
223 |
m_wsfilter = whiteSpaceFilter; |
|
224 |
m_xstrf = xstringfactory; |
|
225 |
m_indexing = doIndexing; |
|
226 |
||
227 |
if (doIndexing) |
|
228 |
{ |
|
229 |
m_expandedNameTable = new ExpandedNameTable(); |
|
230 |
} |
|
231 |
else |
|
232 |
{ |
|
233 |
// Note that this fails if we aren't talking to an instance of |
|
234 |
// DTMManagerDefault |
|
235 |
m_expandedNameTable = m_mgrDefault.getExpandedNameTable(this); |
|
236 |
} |
|
237 |
||
238 |
if (null != whiteSpaceFilter) |
|
239 |
{ |
|
240 |
m_shouldStripWhitespaceStack = new BoolStack(); |
|
241 |
||
242 |
pushShouldStripWhitespace(false); |
|
243 |
} |
|
244 |
} |
|
245 |
||
246 |
/** |
|
247 |
* Ensure that the size of the element indexes can hold the information. |
|
248 |
* |
|
249 |
* @param namespaceID Namespace ID index. |
|
250 |
* @param LocalNameID Local name ID. |
|
251 |
*/ |
|
252 |
protected void ensureSizeOfIndex(int namespaceID, int LocalNameID) |
|
253 |
{ |
|
254 |
||
255 |
if (null == m_elemIndexes) |
|
256 |
{ |
|
257 |
m_elemIndexes = new int[namespaceID + 20][][]; |
|
258 |
} |
|
259 |
else if (m_elemIndexes.length <= namespaceID) |
|
260 |
{ |
|
261 |
int[][][] indexes = m_elemIndexes; |
|
262 |
||
263 |
m_elemIndexes = new int[namespaceID + 20][][]; |
|
264 |
||
265 |
System.arraycopy(indexes, 0, m_elemIndexes, 0, indexes.length); |
|
266 |
} |
|
267 |
||
268 |
int[][] localNameIndex = m_elemIndexes[namespaceID]; |
|
269 |
||
270 |
if (null == localNameIndex) |
|
271 |
{ |
|
272 |
localNameIndex = new int[LocalNameID + 100][]; |
|
273 |
m_elemIndexes[namespaceID] = localNameIndex; |
|
274 |
} |
|
275 |
else if (localNameIndex.length <= LocalNameID) |
|
276 |
{ |
|
277 |
int[][] indexes = localNameIndex; |
|
278 |
||
279 |
localNameIndex = new int[LocalNameID + 100][]; |
|
280 |
||
281 |
System.arraycopy(indexes, 0, localNameIndex, 0, indexes.length); |
|
282 |
||
283 |
m_elemIndexes[namespaceID] = localNameIndex; |
|
284 |
} |
|
285 |
||
286 |
int[] elemHandles = localNameIndex[LocalNameID]; |
|
287 |
||
288 |
if (null == elemHandles) |
|
289 |
{ |
|
290 |
elemHandles = new int[128]; |
|
291 |
localNameIndex[LocalNameID] = elemHandles; |
|
292 |
elemHandles[0] = 1; |
|
293 |
} |
|
294 |
else if (elemHandles.length <= elemHandles[0] + 1) |
|
295 |
{ |
|
296 |
int[] indexes = elemHandles; |
|
297 |
||
298 |
elemHandles = new int[elemHandles[0] + 1024]; |
|
299 |
||
300 |
System.arraycopy(indexes, 0, elemHandles, 0, indexes.length); |
|
301 |
||
302 |
localNameIndex[LocalNameID] = elemHandles; |
|
303 |
} |
|
304 |
} |
|
305 |
||
306 |
/** |
|
307 |
* Add a node to the element indexes. The node will not be added unless |
|
308 |
* it's an element. |
|
309 |
* |
|
310 |
* @param expandedTypeID The expanded type ID of the node. |
|
311 |
* @param identity The node identity index. |
|
312 |
*/ |
|
313 |
protected void indexNode(int expandedTypeID, int identity) |
|
314 |
{ |
|
315 |
||
316 |
ExpandedNameTable ent = m_expandedNameTable; |
|
317 |
short type = ent.getType(expandedTypeID); |
|
318 |
||
319 |
if (DTM.ELEMENT_NODE == type) |
|
320 |
{ |
|
321 |
int namespaceID = ent.getNamespaceID(expandedTypeID); |
|
322 |
int localNameID = ent.getLocalNameID(expandedTypeID); |
|
323 |
||
324 |
ensureSizeOfIndex(namespaceID, localNameID); |
|
325 |
||
326 |
int[] index = m_elemIndexes[namespaceID][localNameID]; |
|
327 |
||
328 |
index[index[0]] = identity; |
|
329 |
||
330 |
index[0]++; |
|
331 |
} |
|
332 |
} |
|
333 |
||
334 |
/** |
|
335 |
* Find the first index that occurs in the list that is greater than or |
|
336 |
* equal to the given value. |
|
337 |
* |
|
338 |
* @param list A list of integers. |
|
339 |
* @param start The start index to begin the search. |
|
340 |
* @param len The number of items to search. |
|
341 |
* @param value Find the slot that has a value that is greater than or |
|
342 |
* identical to this argument. |
|
343 |
* |
|
344 |
* @return The index in the list of the slot that is higher or identical |
|
345 |
* to the identity argument, or -1 if no node is higher or equal. |
|
346 |
*/ |
|
347 |
protected int findGTE(int[] list, int start, int len, int value) |
|
348 |
{ |
|
349 |
||
350 |
int low = start; |
|
351 |
int high = start + (len - 1); |
|
352 |
int end = high; |
|
353 |
||
354 |
while (low <= high) |
|
355 |
{ |
|
356 |
int mid = (low + high) / 2; |
|
357 |
int c = list[mid]; |
|
358 |
||
359 |
if (c > value) |
|
360 |
high = mid - 1; |
|
361 |
else if (c < value) |
|
362 |
low = mid + 1; |
|
363 |
else |
|
364 |
return mid; |
|
365 |
} |
|
366 |
||
367 |
return (low <= end && list[low] > value) ? low : -1; |
|
368 |
} |
|
369 |
||
370 |
/** |
|
371 |
* Find the first matching element from the index at or after the |
|
372 |
* given node. |
|
373 |
* |
|
374 |
* @param nsIndex The namespace index lookup. |
|
375 |
* @param lnIndex The local name index lookup. |
|
376 |
* @param firstPotential The first potential match that is worth looking at. |
|
377 |
* |
|
378 |
* @return The first node that is greater than or equal to the |
|
379 |
* firstPotential argument, or DTM.NOTPROCESSED if not found. |
|
380 |
*/ |
|
381 |
int findElementFromIndex(int nsIndex, int lnIndex, int firstPotential) |
|
382 |
{ |
|
383 |
||
384 |
int[][][] indexes = m_elemIndexes; |
|
385 |
||
386 |
if (null != indexes && nsIndex < indexes.length) |
|
387 |
{ |
|
388 |
int[][] lnIndexs = indexes[nsIndex]; |
|
389 |
||
390 |
if (null != lnIndexs && lnIndex < lnIndexs.length) |
|
391 |
{ |
|
392 |
int[] elems = lnIndexs[lnIndex]; |
|
393 |
||
394 |
if (null != elems) |
|
395 |
{ |
|
396 |
int pos = findGTE(elems, 1, elems[0], firstPotential); |
|
397 |
||
398 |
if (pos > -1) |
|
399 |
{ |
|
400 |
return elems[pos]; |
|
401 |
} |
|
402 |
} |
|
403 |
} |
|
404 |
} |
|
405 |
||
406 |
return NOTPROCESSED; |
|
407 |
} |
|
408 |
||
409 |
/** |
|
410 |
* Get the next node identity value in the list, and call the iterator |
|
411 |
* if it hasn't been added yet. |
|
412 |
* |
|
413 |
* @param identity The node identity (index). |
|
414 |
* @return identity+1, or DTM.NULL. |
|
415 |
*/ |
|
416 |
protected abstract int getNextNodeIdentity(int identity); |
|
417 |
||
418 |
/** |
|
419 |
* This method should try and build one or more nodes in the table. |
|
420 |
* |
|
421 |
* @return The true if a next node is found or false if |
|
422 |
* there are no more nodes. |
|
423 |
*/ |
|
424 |
protected abstract boolean nextNode(); |
|
425 |
||
426 |
/** |
|
427 |
* Get the number of nodes that have been added. |
|
428 |
* |
|
429 |
* @return the number of nodes that have been mapped. |
|
430 |
*/ |
|
431 |
protected abstract int getNumberOfNodes(); |
|
432 |
||
433 |
/** Stateless axis traversers, lazely built. */ |
|
434 |
protected DTMAxisTraverser[] m_traversers; |
|
435 |
||
436 |
// /** |
|
437 |
// * Ensure that the size of the information arrays can hold another entry |
|
438 |
// * at the given index. |
|
439 |
// * |
|
440 |
// * @param index On exit from this function, the information arrays sizes must be |
|
441 |
// * at least index+1. |
|
442 |
// */ |
|
443 |
// protected void ensureSize(int index) |
|
444 |
// { |
|
445 |
// // We've cut over to Suballocated*Vector, which are self-sizing. |
|
446 |
// } |
|
447 |
||
448 |
/** |
|
449 |
* Get the simple type ID for the given node identity. |
|
450 |
* |
|
451 |
* @param identity The node identity. |
|
452 |
* |
|
453 |
* @return The simple type ID, or DTM.NULL. |
|
454 |
*/ |
|
455 |
protected short _type(int identity) |
|
456 |
{ |
|
457 |
||
458 |
int info = _exptype(identity); |
|
459 |
||
460 |
if (NULL != info) |
|
461 |
return m_expandedNameTable.getType(info); |
|
462 |
else |
|
463 |
return NULL; |
|
464 |
} |
|
465 |
||
466 |
/** |
|
467 |
* Get the expanded type ID for the given node identity. |
|
468 |
* |
|
469 |
* @param identity The node identity. |
|
470 |
* |
|
471 |
* @return The expanded type ID, or DTM.NULL. |
|
472 |
*/ |
|
473 |
protected int _exptype(int identity) |
|
474 |
{ |
|
475 |
if (identity == DTM.NULL) |
|
476 |
return NULL; |
|
477 |
// Reorganized test and loop into single flow |
|
478 |
// Tiny performance improvement, saves a few bytes of code, clearer. |
|
479 |
// %OPT% Other internal getters could be treated simliarly |
|
480 |
while (identity>=m_size) |
|
481 |
{ |
|
482 |
if (!nextNode() && identity >= m_size) |
|
483 |
return NULL; |
|
484 |
} |
|
485 |
return m_exptype.elementAt(identity); |
|
486 |
||
487 |
} |
|
488 |
||
489 |
/** |
|
490 |
* Get the level in the tree for the given node identity. |
|
491 |
* |
|
492 |
* @param identity The node identity. |
|
493 |
* |
|
494 |
* @return The tree level, or DTM.NULL. |
|
495 |
*/ |
|
496 |
protected int _level(int identity) |
|
497 |
{ |
|
498 |
while (identity>=m_size) |
|
499 |
{ |
|
500 |
boolean isMore = nextNode(); |
|
501 |
if (!isMore && identity >= m_size) |
|
502 |
return NULL; |
|
503 |
} |
|
504 |
||
505 |
int i=0; |
|
506 |
while(NULL != (identity=_parent(identity))) |
|
507 |
++i; |
|
508 |
return i; |
|
509 |
} |
|
510 |
||
511 |
/** |
|
512 |
* Get the first child for the given node identity. |
|
513 |
* |
|
514 |
* @param identity The node identity. |
|
515 |
* |
|
516 |
* @return The first child identity, or DTM.NULL. |
|
517 |
*/ |
|
518 |
protected int _firstch(int identity) |
|
519 |
{ |
|
520 |
||
521 |
// Boiler-plate code for each of the _xxx functions, except for the array. |
|
522 |
int info = (identity >= m_size) ? NOTPROCESSED : m_firstch.elementAt(identity); |
|
523 |
||
524 |
// Check to see if the information requested has been processed, and, |
|
525 |
// if not, advance the iterator until we the information has been |
|
526 |
// processed. |
|
527 |
while (info == NOTPROCESSED) |
|
528 |
{ |
|
529 |
boolean isMore = nextNode(); |
|
530 |
||
531 |
if (identity >= m_size &&!isMore) |
|
532 |
return NULL; |
|
533 |
else |
|
534 |
{ |
|
535 |
info = m_firstch.elementAt(identity); |
|
536 |
if(info == NOTPROCESSED && !isMore) |
|
537 |
return NULL; |
|
538 |
} |
|
539 |
} |
|
540 |
||
541 |
return info; |
|
542 |
} |
|
543 |
||
544 |
/** |
|
545 |
* Get the next sibling for the given node identity. |
|
546 |
* |
|
547 |
* @param identity The node identity. |
|
548 |
* |
|
549 |
* @return The next sibling identity, or DTM.NULL. |
|
550 |
*/ |
|
551 |
protected int _nextsib(int identity) |
|
552 |
{ |
|
553 |
// Boiler-plate code for each of the _xxx functions, except for the array. |
|
554 |
int info = (identity >= m_size) ? NOTPROCESSED : m_nextsib.elementAt(identity); |
|
555 |
||
556 |
// Check to see if the information requested has been processed, and, |
|
557 |
// if not, advance the iterator until we the information has been |
|
558 |
// processed. |
|
559 |
while (info == NOTPROCESSED) |
|
560 |
{ |
|
561 |
boolean isMore = nextNode(); |
|
562 |
||
563 |
if (identity >= m_size &&!isMore) |
|
564 |
return NULL; |
|
565 |
else |
|
566 |
{ |
|
567 |
info = m_nextsib.elementAt(identity); |
|
568 |
if(info == NOTPROCESSED && !isMore) |
|
569 |
return NULL; |
|
570 |
} |
|
571 |
} |
|
572 |
||
573 |
return info; |
|
574 |
} |
|
575 |
||
576 |
/** |
|
577 |
* Get the previous sibling for the given node identity. |
|
578 |
* |
|
579 |
* @param identity The node identity. |
|
580 |
* |
|
581 |
* @return The previous sibling identity, or DTM.NULL. |
|
582 |
*/ |
|
583 |
protected int _prevsib(int identity) |
|
584 |
{ |
|
585 |
||
586 |
if (identity < m_size) |
|
587 |
return m_prevsib.elementAt(identity); |
|
588 |
||
589 |
// Check to see if the information requested has been processed, and, |
|
590 |
// if not, advance the iterator until we the information has been |
|
591 |
// processed. |
|
592 |
while (true) |
|
593 |
{ |
|
594 |
boolean isMore = nextNode(); |
|
595 |
||
596 |
if (identity >= m_size && !isMore) |
|
597 |
return NULL; |
|
598 |
else if (identity < m_size) |
|
599 |
return m_prevsib.elementAt(identity); |
|
600 |
} |
|
601 |
} |
|
602 |
||
603 |
/** |
|
604 |
* Get the parent for the given node identity. |
|
605 |
* |
|
606 |
* @param identity The node identity. |
|
607 |
* |
|
608 |
* @return The parent identity, or DTM.NULL. |
|
609 |
*/ |
|
610 |
protected int _parent(int identity) |
|
611 |
{ |
|
612 |
||
613 |
if (identity < m_size) |
|
614 |
return m_parent.elementAt(identity); |
|
615 |
||
616 |
// Check to see if the information requested has been processed, and, |
|
617 |
// if not, advance the iterator until we the information has been |
|
618 |
// processed. |
|
619 |
while (true) |
|
620 |
{ |
|
621 |
boolean isMore = nextNode(); |
|
622 |
||
623 |
if (identity >= m_size && !isMore) |
|
624 |
return NULL; |
|
625 |
else if (identity < m_size) |
|
626 |
return m_parent.elementAt(identity); |
|
627 |
} |
|
628 |
} |
|
629 |
||
630 |
/** |
|
631 |
* Diagnostics function to dump the DTM. |
|
632 |
*/ |
|
633 |
public void dumpDTM(OutputStream os) |
|
634 |
{ |
|
635 |
try |
|
636 |
{ |
|
637 |
if(os==null) |
|
638 |
{ |
|
639 |
File f = new File("DTMDump"+((Object)this).hashCode()+".txt"); |
|
640 |
System.err.println("Dumping... "+f.getAbsolutePath()); |
|
641 |
os=new FileOutputStream(f); |
|
642 |
} |
|
643 |
PrintStream ps = new PrintStream(os); |
|
644 |
||
645 |
while (nextNode()){} |
|
646 |
||
647 |
int nRecords = m_size; |
|
648 |
||
649 |
ps.println("Total nodes: " + nRecords); |
|
650 |
||
651 |
for (int index = 0; index < nRecords; ++index) |
|
652 |
{ |
|
653 |
int i=makeNodeHandle(index); |
|
654 |
ps.println("=========== index=" + index + " handle=" + i + " ==========="); |
|
655 |
ps.println("NodeName: " + getNodeName(i)); |
|
656 |
ps.println("NodeNameX: " + getNodeNameX(i)); |
|
657 |
ps.println("LocalName: " + getLocalName(i)); |
|
658 |
ps.println("NamespaceURI: " + getNamespaceURI(i)); |
|
659 |
ps.println("Prefix: " + getPrefix(i)); |
|
660 |
||
661 |
int exTypeID = _exptype(index); |
|
662 |
||
663 |
ps.println("Expanded Type ID: " |
|
664 |
+ Integer.toHexString(exTypeID)); |
|
665 |
||
666 |
int type = _type(index); |
|
667 |
String typestring; |
|
668 |
||
669 |
switch (type) |
|
670 |
{ |
|
671 |
case DTM.ATTRIBUTE_NODE : |
|
672 |
typestring = "ATTRIBUTE_NODE"; |
|
673 |
break; |
|
674 |
case DTM.CDATA_SECTION_NODE : |
|
675 |
typestring = "CDATA_SECTION_NODE"; |
|
676 |
break; |
|
677 |
case DTM.COMMENT_NODE : |
|
678 |
typestring = "COMMENT_NODE"; |
|
679 |
break; |
|
680 |
case DTM.DOCUMENT_FRAGMENT_NODE : |
|
681 |
typestring = "DOCUMENT_FRAGMENT_NODE"; |
|
682 |
break; |
|
683 |
case DTM.DOCUMENT_NODE : |
|
684 |
typestring = "DOCUMENT_NODE"; |
|
685 |
break; |
|
686 |
case DTM.DOCUMENT_TYPE_NODE : |
|
687 |
typestring = "DOCUMENT_NODE"; |
|
688 |
break; |
|
689 |
case DTM.ELEMENT_NODE : |
|
690 |
typestring = "ELEMENT_NODE"; |
|
691 |
break; |
|
692 |
case DTM.ENTITY_NODE : |
|
693 |
typestring = "ENTITY_NODE"; |
|
694 |
break; |
|
695 |
case DTM.ENTITY_REFERENCE_NODE : |
|
696 |
typestring = "ENTITY_REFERENCE_NODE"; |
|
697 |
break; |
|
698 |
case DTM.NAMESPACE_NODE : |
|
699 |
typestring = "NAMESPACE_NODE"; |
|
700 |
break; |
|
701 |
case DTM.NOTATION_NODE : |
|
702 |
typestring = "NOTATION_NODE"; |
|
703 |
break; |
|
704 |
case DTM.NULL : |
|
705 |
typestring = "NULL"; |
|
706 |
break; |
|
707 |
case DTM.PROCESSING_INSTRUCTION_NODE : |
|
708 |
typestring = "PROCESSING_INSTRUCTION_NODE"; |
|
709 |
break; |
|
710 |
case DTM.TEXT_NODE : |
|
711 |
typestring = "TEXT_NODE"; |
|
712 |
break; |
|
713 |
default : |
|
714 |
typestring = "Unknown!"; |
|
715 |
break; |
|
716 |
} |
|
717 |
||
718 |
ps.println("Type: " + typestring); |
|
719 |
||
720 |
int firstChild = _firstch(index); |
|
721 |
||
722 |
if (DTM.NULL == firstChild) |
|
723 |
ps.println("First child: DTM.NULL"); |
|
724 |
else if (NOTPROCESSED == firstChild) |
|
725 |
ps.println("First child: NOTPROCESSED"); |
|
726 |
else |
|
727 |
ps.println("First child: " + firstChild); |
|
728 |
||
729 |
if (m_prevsib != null) |
|
730 |
{ |
|
731 |
int prevSibling = _prevsib(index); |
|
732 |
||
733 |
if (DTM.NULL == prevSibling) |
|
734 |
ps.println("Prev sibling: DTM.NULL"); |
|
735 |
else if (NOTPROCESSED == prevSibling) |
|
736 |
ps.println("Prev sibling: NOTPROCESSED"); |
|
737 |
else |
|
738 |
ps.println("Prev sibling: " + prevSibling); |
|
739 |
} |
|
740 |
||
741 |
int nextSibling = _nextsib(index); |
|
742 |
||
743 |
if (DTM.NULL == nextSibling) |
|
744 |
ps.println("Next sibling: DTM.NULL"); |
|
745 |
else if (NOTPROCESSED == nextSibling) |
|
746 |
ps.println("Next sibling: NOTPROCESSED"); |
|
747 |
else |
|
748 |
ps.println("Next sibling: " + nextSibling); |
|
749 |
||
750 |
int parent = _parent(index); |
|
751 |
||
752 |
if (DTM.NULL == parent) |
|
753 |
ps.println("Parent: DTM.NULL"); |
|
754 |
else if (NOTPROCESSED == parent) |
|
755 |
ps.println("Parent: NOTPROCESSED"); |
|
756 |
else |
|
757 |
ps.println("Parent: " + parent); |
|
758 |
||
759 |
int level = _level(index); |
|
760 |
||
761 |
ps.println("Level: " + level); |
|
762 |
ps.println("Node Value: " + getNodeValue(i)); |
|
763 |
ps.println("String Value: " + getStringValue(i)); |
|
764 |
} |
|
765 |
} |
|
766 |
catch(IOException ioe) |
|
767 |
{ |
|
768 |
ioe.printStackTrace(System.err); |
|
769 |
throw new RuntimeException(ioe.getMessage()); |
|
770 |
} |
|
771 |
} |
|
772 |
||
773 |
/** |
|
774 |
* Diagnostics function to dump a single node. |
|
775 |
* |
|
776 |
* %REVIEW% KNOWN GLITCH: If you pass it a node index rather than a |
|
777 |
* node handle, it works just fine... but the displayed identity |
|
778 |
* number before the colon is different, which complicates comparing |
|
779 |
* it with nodes printed the other way. We could always OR the DTM ID |
|
780 |
* into the value, to suppress that distinction... |
|
781 |
* |
|
782 |
* %REVIEW% This might want to be moved up to DTMDefaultBase, or possibly |
|
783 |
* DTM itself, since it's a useful diagnostic and uses only DTM's public |
|
784 |
* APIs. |
|
785 |
*/ |
|
786 |
public String dumpNode(int nodeHandle) |
|
787 |
{ |
|
788 |
if(nodeHandle==DTM.NULL) |
|
789 |
return "[null]"; |
|
790 |
||
791 |
String typestring; |
|
792 |
switch (getNodeType(nodeHandle)) |
|
793 |
{ |
|
794 |
case DTM.ATTRIBUTE_NODE : |
|
795 |
typestring = "ATTR"; |
|
796 |
break; |
|
797 |
case DTM.CDATA_SECTION_NODE : |
|
798 |
typestring = "CDATA"; |
|
799 |
break; |
|
800 |
case DTM.COMMENT_NODE : |
|
801 |
typestring = "COMMENT"; |
|
802 |
break; |
|
803 |
case DTM.DOCUMENT_FRAGMENT_NODE : |
|
804 |
typestring = "DOC_FRAG"; |
|
805 |
break; |
|
806 |
case DTM.DOCUMENT_NODE : |
|
807 |
typestring = "DOC"; |
|
808 |
break; |
|
809 |
case DTM.DOCUMENT_TYPE_NODE : |
|
810 |
typestring = "DOC_TYPE"; |
|
811 |
break; |
|
812 |
case DTM.ELEMENT_NODE : |
|
813 |
typestring = "ELEMENT"; |
|
814 |
break; |
|
815 |
case DTM.ENTITY_NODE : |
|
816 |
typestring = "ENTITY"; |
|
817 |
break; |
|
818 |
case DTM.ENTITY_REFERENCE_NODE : |
|
819 |
typestring = "ENT_REF"; |
|
820 |
break; |
|
821 |
case DTM.NAMESPACE_NODE : |
|
822 |
typestring = "NAMESPACE"; |
|
823 |
break; |
|
824 |
case DTM.NOTATION_NODE : |
|
825 |
typestring = "NOTATION"; |
|
826 |
break; |
|
827 |
case DTM.NULL : |
|
828 |
typestring = "null"; |
|
829 |
break; |
|
830 |
case DTM.PROCESSING_INSTRUCTION_NODE : |
|
831 |
typestring = "PI"; |
|
832 |
break; |
|
833 |
case DTM.TEXT_NODE : |
|
834 |
typestring = "TEXT"; |
|
835 |
break; |
|
836 |
default : |
|
837 |
typestring = "Unknown!"; |
|
838 |
break; |
|
839 |
} |
|
840 |
||
12458 | 841 |
return "[" + nodeHandle + ": " + typestring + |
842 |
"(0x" + Integer.toHexString(getExpandedTypeID(nodeHandle)) + ") " + |
|
843 |
getNodeNameX(nodeHandle) + " {" + getNamespaceURI(nodeHandle) + "}" + |
|
844 |
"=\"" + getNodeValue(nodeHandle) + "\"]"; |
|
6 | 845 |
} |
846 |
||
847 |
// ========= DTM Implementation Control Functions. ============== |
|
848 |
||
849 |
/** |
|
850 |
* Set an implementation dependent feature. |
|
851 |
* <p> |
|
852 |
* %REVIEW% Do we really expect to set features on DTMs? |
|
853 |
* |
|
854 |
* @param featureId A feature URL. |
|
855 |
* @param state true if this feature should be on, false otherwise. |
|
856 |
*/ |
|
857 |
public void setFeature(String featureId, boolean state){} |
|
858 |
||
859 |
// ========= Document Navigation Functions ========= |
|
860 |
||
861 |
/** |
|
862 |
* Given a node handle, test if it has child nodes. |
|
863 |
* <p> %REVIEW% This is obviously useful at the DOM layer, where it |
|
864 |
* would permit testing this without having to create a proxy |
|
865 |
* node. It's less useful in the DTM API, where |
|
866 |
* (dtm.getFirstChild(nodeHandle)!=DTM.NULL) is just as fast and |
|
867 |
* almost as self-evident. But it's a convenience, and eases porting |
|
868 |
* of DOM code to DTM. </p> |
|
869 |
* |
|
870 |
* @param nodeHandle int Handle of the node. |
|
871 |
* @return int true if the given node has child nodes. |
|
872 |
*/ |
|
873 |
public boolean hasChildNodes(int nodeHandle) |
|
874 |
{ |
|
875 |
||
876 |
int identity = makeNodeIdentity(nodeHandle); |
|
877 |
int firstChild = _firstch(identity); |
|
878 |
||
879 |
return firstChild != DTM.NULL; |
|
880 |
} |
|
881 |
||
882 |
/** Given a node identity, return a node handle. If extended addressing |
|
883 |
* has been used (multiple DTM IDs), we need to map the high bits of the |
|
884 |
* identity into the proper DTM ID. |
|
885 |
* |
|
886 |
* This has been made FINAL to facilitate inlining, since we do not expect |
|
887 |
* any subclass of DTMDefaultBase to ever change the algorithm. (I don't |
|
888 |
* really like doing so, and would love to have an excuse not to...) |
|
889 |
* |
|
890 |
* %REVIEW% Is it worth trying to specialcase small documents? |
|
891 |
* %REVIEW% Should this be exposed at the package/public layers? |
|
892 |
* |
|
893 |
* @param nodeIdentity Internal offset to this node's records. |
|
894 |
* @return NodeHandle (external representation of node) |
|
895 |
* */ |
|
896 |
final public int makeNodeHandle(int nodeIdentity) |
|
897 |
{ |
|
898 |
if(NULL==nodeIdentity) return NULL; |
|
899 |
||
900 |
if(JJK_DEBUG && nodeIdentity>DTMManager.IDENT_NODE_DEFAULT) |
|
901 |
System.err.println("GONK! (only useful in limited situations)"); |
|
902 |
||
903 |
return m_dtmIdent.elementAt(nodeIdentity >>> DTMManager.IDENT_DTM_NODE_BITS) |
|
904 |
+ (nodeIdentity & DTMManager.IDENT_NODE_DEFAULT) ; |
|
905 |
} |
|
906 |
||
907 |
/** Given a node handle, return a node identity. If extended addressing |
|
908 |
* has been used (multiple DTM IDs), we need to map the high bits of the |
|
909 |
* identity into the proper DTM ID and thence find the proper offset |
|
910 |
* to add to the low bits of the identity |
|
911 |
* |
|
912 |
* This has been made FINAL to facilitate inlining, since we do not expect |
|
913 |
* any subclass of DTMDefaultBase to ever change the algorithm. (I don't |
|
914 |
* really like doing so, and would love to have an excuse not to...) |
|
915 |
* |
|
916 |
* %OPT% Performance is critical for this operation. |
|
917 |
* |
|
918 |
* %REVIEW% Should this be exposed at the package/public layers? |
|
919 |
* |
|
920 |
* @param nodeHandle (external representation of node) |
|
921 |
* @return nodeIdentity Internal offset to this node's records. |
|
922 |
* */ |
|
923 |
final public int makeNodeIdentity(int nodeHandle) |
|
924 |
{ |
|
925 |
if(NULL==nodeHandle) return NULL; |
|
926 |
||
927 |
if(m_mgrDefault!=null) |
|
928 |
{ |
|
929 |
// Optimization: use the DTMManagerDefault's fast DTMID-to-offsets |
|
930 |
// table. I'm not wild about this solution but this operation |
|
931 |
// needs need extreme speed. |
|
932 |
||
933 |
int whichDTMindex=nodeHandle>>>DTMManager.IDENT_DTM_NODE_BITS; |
|
934 |
||
935 |
// %REVIEW% Wish I didn't have to perform the pre-test, but |
|
936 |
// someone is apparently asking DTMs whether they contain nodes |
|
937 |
// which really don't belong to them. That's probably a bug |
|
938 |
// which should be fixed, but until it is: |
|
939 |
if(m_mgrDefault.m_dtms[whichDTMindex]!=this) |
|
940 |
return NULL; |
|
941 |
else |
|
942 |
return |
|
943 |
m_mgrDefault.m_dtm_offsets[whichDTMindex] |
|
944 |
| (nodeHandle & DTMManager.IDENT_NODE_DEFAULT); |
|
945 |
} |
|
946 |
||
947 |
int whichDTMid=m_dtmIdent.indexOf(nodeHandle & DTMManager.IDENT_DTM_DEFAULT); |
|
948 |
return (whichDTMid==NULL) |
|
949 |
? NULL |
|
950 |
: (whichDTMid << DTMManager.IDENT_DTM_NODE_BITS) |
|
951 |
+ (nodeHandle & DTMManager.IDENT_NODE_DEFAULT); |
|
952 |
} |
|
953 |
||
954 |
||
955 |
/** |
|
956 |
* Given a node handle, get the handle of the node's first child. |
|
957 |
* If not yet resolved, waits for more nodes to be added to the document and |
|
958 |
* tries again. |
|
959 |
* |
|
960 |
* @param nodeHandle int Handle of the node. |
|
961 |
* @return int DTM node-number of first child, or DTM.NULL to indicate none exists. |
|
962 |
*/ |
|
963 |
public int getFirstChild(int nodeHandle) |
|
964 |
{ |
|
965 |
||
966 |
int identity = makeNodeIdentity(nodeHandle); |
|
967 |
int firstChild = _firstch(identity); |
|
968 |
||
969 |
return makeNodeHandle(firstChild); |
|
970 |
} |
|
971 |
||
972 |
/** |
|
973 |
* Given a node handle, get the handle of the node's first child. |
|
974 |
* If not yet resolved, waits for more nodes to be added to the document and |
|
975 |
* tries again. |
|
976 |
* |
|
977 |
* @param nodeHandle int Handle of the node. |
|
978 |
* @return int DTM node-number of first child, or DTM.NULL to indicate none exists. |
|
979 |
*/ |
|
980 |
public int getTypedFirstChild(int nodeHandle, int nodeType) |
|
981 |
{ |
|
982 |
||
983 |
int firstChild, eType; |
|
984 |
if (nodeType < DTM.NTYPES) { |
|
985 |
for (firstChild = _firstch(makeNodeIdentity(nodeHandle)); |
|
986 |
firstChild != DTM.NULL; |
|
987 |
firstChild = _nextsib(firstChild)) { |
|
988 |
eType = _exptype(firstChild); |
|
989 |
if (eType == nodeType |
|
990 |
|| (eType >= DTM.NTYPES |
|
991 |
&& m_expandedNameTable.getType(eType) == nodeType)) { |
|
992 |
return makeNodeHandle(firstChild); |
|
993 |
} |
|
994 |
} |
|
995 |
} else { |
|
996 |
for (firstChild = _firstch(makeNodeIdentity(nodeHandle)); |
|
997 |
firstChild != DTM.NULL; |
|
998 |
firstChild = _nextsib(firstChild)) { |
|
999 |
if (_exptype(firstChild) == nodeType) { |
|
1000 |
return makeNodeHandle(firstChild); |
|
1001 |
} |
|
1002 |
} |
|
1003 |
} |
|
1004 |
return DTM.NULL; |
|
1005 |
} |
|
1006 |
||
1007 |
/** |
|
1008 |
* Given a node handle, advance to its last child. |
|
1009 |
* If not yet resolved, waits for more nodes to be added to the document and |
|
1010 |
* tries again. |
|
1011 |
* |
|
1012 |
* @param nodeHandle int Handle of the node. |
|
1013 |
* @return int Node-number of last child, |
|
1014 |
* or DTM.NULL to indicate none exists. |
|
1015 |
*/ |
|
1016 |
public int getLastChild(int nodeHandle) |
|
1017 |
{ |
|
1018 |
||
1019 |
int identity = makeNodeIdentity(nodeHandle); |
|
1020 |
int child = _firstch(identity); |
|
1021 |
int lastChild = DTM.NULL; |
|
1022 |
||
1023 |
while (child != DTM.NULL) |
|
1024 |
{ |
|
1025 |
lastChild = child; |
|
1026 |
child = _nextsib(child); |
|
1027 |
} |
|
1028 |
||
1029 |
return makeNodeHandle(lastChild); |
|
1030 |
} |
|
1031 |
||
1032 |
/** |
|
1033 |
* Retrieves an attribute node by by qualified name and namespace URI. |
|
1034 |
* |
|
1035 |
* @param nodeHandle int Handle of the node upon which to look up this attribute.. |
|
1036 |
* @param namespaceURI The namespace URI of the attribute to |
|
1037 |
* retrieve, or null. |
|
1038 |
* @param name The local name of the attribute to |
|
1039 |
* retrieve. |
|
1040 |
* @return The attribute node handle with the specified name ( |
|
1041 |
* <code>nodeName</code>) or <code>DTM.NULL</code> if there is no such |
|
1042 |
* attribute. |
|
1043 |
*/ |
|
1044 |
public abstract int getAttributeNode(int nodeHandle, String namespaceURI, |
|
1045 |
String name); |
|
1046 |
||
1047 |
/** |
|
1048 |
* Given a node handle, get the index of the node's first attribute. |
|
1049 |
* |
|
1050 |
* @param nodeHandle int Handle of the node. |
|
1051 |
* @return Handle of first attribute, or DTM.NULL to indicate none exists. |
|
1052 |
*/ |
|
1053 |
public int getFirstAttribute(int nodeHandle) |
|
1054 |
{ |
|
1055 |
int nodeID = makeNodeIdentity(nodeHandle); |
|
1056 |
||
1057 |
return makeNodeHandle(getFirstAttributeIdentity(nodeID)); |
|
1058 |
} |
|
1059 |
||
1060 |
/** |
|
1061 |
* Given a node identity, get the index of the node's first attribute. |
|
1062 |
* |
|
1063 |
* @param identity int identity of the node. |
|
1064 |
* @return Identity of first attribute, or DTM.NULL to indicate none exists. |
|
1065 |
*/ |
|
1066 |
protected int getFirstAttributeIdentity(int identity) { |
|
1067 |
int type = _type(identity); |
|
1068 |
||
1069 |
if (DTM.ELEMENT_NODE == type) |
|
1070 |
{ |
|
1071 |
// Assume that attributes and namespaces immediately follow the element. |
|
1072 |
while (DTM.NULL != (identity = getNextNodeIdentity(identity))) |
|
1073 |
{ |
|
1074 |
||
1075 |
// Assume this can not be null. |
|
1076 |
type = _type(identity); |
|
1077 |
||
1078 |
if (type == DTM.ATTRIBUTE_NODE) |
|
1079 |
{ |
|
1080 |
return identity; |
|
1081 |
} |
|
1082 |
else if (DTM.NAMESPACE_NODE != type) |
|
1083 |
{ |
|
1084 |
break; |
|
1085 |
} |
|
1086 |
} |
|
1087 |
} |
|
1088 |
||
1089 |
return DTM.NULL; |
|
1090 |
} |
|
1091 |
||
1092 |
/** |
|
1093 |
* Given a node handle and an expanded type ID, get the index of the node's |
|
1094 |
* attribute of that type, if any. |
|
1095 |
* |
|
1096 |
* @param nodeHandle int Handle of the node. |
|
1097 |
* @param attType int expanded type ID of the required attribute. |
|
1098 |
* @return Handle of attribute of the required type, or DTM.NULL to indicate |
|
1099 |
* none exists. |
|
1100 |
*/ |
|
1101 |
protected int getTypedAttribute(int nodeHandle, int attType) { |
|
1102 |
int type = getNodeType(nodeHandle); |
|
1103 |
if (DTM.ELEMENT_NODE == type) { |
|
1104 |
int identity = makeNodeIdentity(nodeHandle); |
|
1105 |
||
1106 |
while (DTM.NULL != (identity = getNextNodeIdentity(identity))) |
|
1107 |
{ |
|
1108 |
type = _type(identity); |
|
1109 |
||
1110 |
if (type == DTM.ATTRIBUTE_NODE) |
|
1111 |
{ |
|
1112 |
if (_exptype(identity) == attType) return makeNodeHandle(identity); |
|
1113 |
} |
|
1114 |
else if (DTM.NAMESPACE_NODE != type) |
|
1115 |
{ |
|
1116 |
break; |
|
1117 |
} |
|
1118 |
} |
|
1119 |
} |
|
1120 |
||
1121 |
return DTM.NULL; |
|
1122 |
} |
|
1123 |
||
1124 |
/** |
|
1125 |
* Given a node handle, advance to its next sibling. |
|
1126 |
* If not yet resolved, waits for more nodes to be added to the document and |
|
1127 |
* tries again. |
|
1128 |
* @param nodeHandle int Handle of the node. |
|
1129 |
* @return int Node-number of next sibling, |
|
1130 |
* or DTM.NULL to indicate none exists. |
|
1131 |
*/ |
|
1132 |
public int getNextSibling(int nodeHandle) |
|
1133 |
{ |
|
1134 |
if (nodeHandle == DTM.NULL) |
|
1135 |
return DTM.NULL; |
|
1136 |
return makeNodeHandle(_nextsib(makeNodeIdentity(nodeHandle))); |
|
1137 |
} |
|
1138 |
||
1139 |
/** |
|
1140 |
* Given a node handle, advance to its next sibling. |
|
1141 |
* If not yet resolved, waits for more nodes to be added to the document and |
|
1142 |
* tries again. |
|
1143 |
* @param nodeHandle int Handle of the node. |
|
1144 |
* @return int Node-number of next sibling, |
|
1145 |
* or DTM.NULL to indicate none exists. |
|
1146 |
*/ |
|
1147 |
public int getTypedNextSibling(int nodeHandle, int nodeType) |
|
1148 |
{ |
|
1149 |
if (nodeHandle == DTM.NULL) |
|
1150 |
return DTM.NULL; |
|
1151 |
int node = makeNodeIdentity(nodeHandle); |
|
1152 |
int eType; |
|
1153 |
while ((node = _nextsib(node)) != DTM.NULL && |
|
1154 |
((eType = _exptype(node)) != nodeType && |
|
1155 |
m_expandedNameTable.getType(eType)!= nodeType)); |
|
1156 |
//_type(node) != nodeType)); |
|
1157 |
||
1158 |
return (node == DTM.NULL ? DTM.NULL : makeNodeHandle(node)); |
|
1159 |
} |
|
1160 |
||
1161 |
/** |
|
1162 |
* Given a node handle, find its preceeding sibling. |
|
1163 |
* WARNING: DTM is asymmetric; this operation is resolved by search, and is |
|
1164 |
* relatively expensive. |
|
1165 |
* |
|
1166 |
* @param nodeHandle the id of the node. |
|
1167 |
* @return int Node-number of the previous sib, |
|
1168 |
* or DTM.NULL to indicate none exists. |
|
1169 |
*/ |
|
1170 |
public int getPreviousSibling(int nodeHandle) |
|
1171 |
{ |
|
1172 |
if (nodeHandle == DTM.NULL) |
|
1173 |
return DTM.NULL; |
|
1174 |
||
1175 |
if (m_prevsib != null) |
|
1176 |
return makeNodeHandle(_prevsib(makeNodeIdentity(nodeHandle))); |
|
1177 |
else |
|
1178 |
{ |
|
1179 |
// If the previous sibling array is not built, we get at |
|
1180 |
// the previous sibling using the parent, firstch and |
|
1181 |
// nextsib arrays. |
|
1182 |
int nodeID = makeNodeIdentity(nodeHandle); |
|
1183 |
int parent = _parent(nodeID); |
|
1184 |
int node = _firstch(parent); |
|
1185 |
int result = DTM.NULL; |
|
1186 |
while (node != nodeID) |
|
1187 |
{ |
|
1188 |
result = node; |
|
1189 |
node = _nextsib(node); |
|
1190 |
} |
|
1191 |
return makeNodeHandle(result); |
|
1192 |
} |
|
1193 |
} |
|
1194 |
||
1195 |
/** |
|
1196 |
* Given a node handle, advance to the next attribute. |
|
1197 |
* If an attr, we advance to |
|
1198 |
* the next attr on the same node. If not an attribute, we return NULL. |
|
1199 |
* |
|
1200 |
* @param nodeHandle int Handle of the node. |
|
1201 |
* @return int DTM node-number of the resolved attr, |
|
1202 |
* or DTM.NULL to indicate none exists. |
|
1203 |
*/ |
|
1204 |
public int getNextAttribute(int nodeHandle) { |
|
1205 |
int nodeID = makeNodeIdentity(nodeHandle); |
|
1206 |
||
1207 |
if (_type(nodeID) == DTM.ATTRIBUTE_NODE) { |
|
1208 |
return makeNodeHandle(getNextAttributeIdentity(nodeID)); |
|
1209 |
} |
|
1210 |
||
1211 |
return DTM.NULL; |
|
1212 |
} |
|
1213 |
||
1214 |
/** |
|
1215 |
* Given a node identity for an attribute, advance to the next attribute. |
|
1216 |
* |
|
1217 |
* @param identity int identity of the attribute node. This |
|
1218 |
* <strong>must</strong> be an attribute node. |
|
1219 |
* |
|
1220 |
* @return int DTM node-identity of the resolved attr, |
|
1221 |
* or DTM.NULL to indicate none exists. |
|
1222 |
* |
|
1223 |
*/ |
|
1224 |
protected int getNextAttributeIdentity(int identity) { |
|
1225 |
// Assume that attributes and namespace nodes immediately follow the element |
|
1226 |
while (DTM.NULL != (identity = getNextNodeIdentity(identity))) { |
|
1227 |
int type = _type(identity); |
|
1228 |
||
1229 |
if (type == DTM.ATTRIBUTE_NODE) { |
|
1230 |
return identity; |
|
1231 |
} else if (type != DTM.NAMESPACE_NODE) { |
|
1232 |
break; |
|
1233 |
} |
|
1234 |
} |
|
1235 |
||
1236 |
return DTM.NULL; |
|
1237 |
} |
|
1238 |
||
1239 |
||
1240 |
/** Build table of namespace declaration |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
1241 |
* locations during DTM construction. Table is aArrayList<>of |
6 | 1242 |
* SuballocatedIntVectors containing the namespace node HANDLES declared at |
1243 |
* that ID, plus an SuballocatedIntVector of the element node INDEXES at which |
|
1244 |
* these declarations appeared. |
|
1245 |
* |
|
1246 |
* NOTE: Since this occurs during model build, nodes will be encountered |
|
1247 |
* in doucment order and thus the table will be ordered by element, |
|
1248 |
* permitting binary-search as a possible retrieval optimization. |
|
1249 |
* |
|
1250 |
* %REVIEW% Directly managed arrays rather than vectors? |
|
1251 |
* %REVIEW% Handles or IDs? Given usage, I think handles. |
|
1252 |
* */ |
|
1253 |
protected void declareNamespaceInContext(int elementNodeIndex,int namespaceNodeIndex) |
|
1254 |
{ |
|
1255 |
SuballocatedIntVector nsList=null; |
|
1256 |
if(m_namespaceDeclSets==null) |
|
1257 |
{ |
|
1258 |
||
1259 |
// First |
|
1260 |
m_namespaceDeclSetElements=new SuballocatedIntVector(32); |
|
1261 |
m_namespaceDeclSetElements.addElement(elementNodeIndex); |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
1262 |
m_namespaceDeclSets=new Vector<>(); |
6 | 1263 |
nsList=new SuballocatedIntVector(32); |
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
1264 |
m_namespaceDeclSets.add(nsList); |
6 | 1265 |
} |
1266 |
else |
|
1267 |
{ |
|
1268 |
// Most recent. May be -1 (none) if DTM was pruned. |
|
1269 |
// %OPT% Is there a lastElement() method? Should there be? |
|
1270 |
int last=m_namespaceDeclSetElements.size()-1; |
|
1271 |
||
1272 |
if(last>=0 && elementNodeIndex==m_namespaceDeclSetElements.elementAt(last)) |
|
1273 |
{ |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
1274 |
nsList=m_namespaceDeclSets.get(last); |
6 | 1275 |
} |
1276 |
} |
|
1277 |
if(nsList==null) |
|
1278 |
{ |
|
1279 |
m_namespaceDeclSetElements.addElement(elementNodeIndex); |
|
1280 |
||
1281 |
SuballocatedIntVector inherited = |
|
1282 |
findNamespaceContext(_parent(elementNodeIndex)); |
|
1283 |
||
1284 |
if (inherited!=null) { |
|
1285 |
// %OPT% Count-down might be faster, but debuggability may |
|
1286 |
// be better this way, and if we ever decide we want to |
|
1287 |
// keep this ordered by expanded-type... |
|
1288 |
int isize=inherited.size(); |
|
1289 |
||
1290 |
// Base the size of a new namespace list on the |
|
1291 |
// size of the inherited list - but within reason! |
|
1292 |
nsList=new SuballocatedIntVector(Math.max(Math.min(isize+16,2048), |
|
1293 |
32)); |
|
1294 |
||
1295 |
for(int i=0;i<isize;++i) |
|
1296 |
{ |
|
1297 |
nsList.addElement(inherited.elementAt(i)); |
|
1298 |
} |
|
1299 |
} else { |
|
1300 |
nsList=new SuballocatedIntVector(32); |
|
1301 |
} |
|
1302 |
||
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
1303 |
m_namespaceDeclSets.add(nsList); |
6 | 1304 |
} |
1305 |
||
1306 |
// Handle overwriting inherited. |
|
1307 |
// %OPT% Keep sorted? (By expanded-name rather than by doc order...) |
|
1308 |
// Downside: Would require insertElementAt if not found, |
|
1309 |
// which has recopying costs. But these are generally short lists... |
|
1310 |
int newEType=_exptype(namespaceNodeIndex); |
|
1311 |
||
1312 |
for(int i=nsList.size()-1;i>=0;--i) |
|
1313 |
{ |
|
1314 |
if(newEType==getExpandedTypeID(nsList.elementAt(i))) |
|
1315 |
{ |
|
1316 |
nsList.setElementAt(makeNodeHandle(namespaceNodeIndex),i); |
|
1317 |
return; |
|
1318 |
} |
|
1319 |
} |
|
1320 |
nsList.addElement(makeNodeHandle(namespaceNodeIndex)); |
|
1321 |
} |
|
1322 |
||
1323 |
/** Retrieve list of namespace declaration locations |
|
1324 |
* active at this node. List is an SuballocatedIntVector whose |
|
1325 |
* entries are the namespace node HANDLES declared at that ID. |
|
1326 |
* |
|
1327 |
* %REVIEW% Directly managed arrays rather than vectors? |
|
1328 |
* %REVIEW% Handles or IDs? Given usage, I think handles. |
|
1329 |
* */ |
|
1330 |
protected SuballocatedIntVector findNamespaceContext(int elementNodeIndex) |
|
1331 |
{ |
|
1332 |
if (null!=m_namespaceDeclSetElements) |
|
1333 |
{ |
|
1334 |
// %OPT% Is binary-search really saving us a lot versus linear? |
|
1335 |
// (... It may be, in large docs with many NS decls.) |
|
1336 |
int wouldBeAt=findInSortedSuballocatedIntVector(m_namespaceDeclSetElements, |
|
1337 |
elementNodeIndex); |
|
1338 |
if(wouldBeAt>=0) // Found it |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
1339 |
return m_namespaceDeclSets.get(wouldBeAt); |
6 | 1340 |
if(wouldBeAt == -1) // -1-wouldbeat == 0 |
1341 |
return null; // Not after anything; definitely not found |
|
1342 |
||
1343 |
// Not found, but we know where it should have been. |
|
1344 |
// Search back until we find an ancestor or run out. |
|
1345 |
wouldBeAt=-1-wouldBeAt; |
|
1346 |
||
1347 |
// Decrement wouldBeAt to find last possible ancestor |
|
1348 |
int candidate=m_namespaceDeclSetElements.elementAt(-- wouldBeAt); |
|
1349 |
int ancestor=_parent(elementNodeIndex); |
|
1350 |
||
1351 |
// Special case: if the candidate is before the given node, and |
|
1352 |
// is in the earliest possible position in the document, it |
|
1353 |
// must have the namespace declarations we're interested in. |
|
1354 |
if (wouldBeAt == 0 && candidate < ancestor) { |
|
1355 |
int rootHandle = getDocumentRoot(makeNodeHandle(elementNodeIndex)); |
|
1356 |
int rootID = makeNodeIdentity(rootHandle); |
|
1357 |
int uppermostNSCandidateID; |
|
1358 |
||
1359 |
if (getNodeType(rootHandle) == DTM.DOCUMENT_NODE) { |
|
1360 |
int ch = _firstch(rootID); |
|
1361 |
uppermostNSCandidateID = (ch != DTM.NULL) ? ch : rootID; |
|
1362 |
} else { |
|
1363 |
uppermostNSCandidateID = rootID; |
|
1364 |
} |
|
1365 |
||
1366 |
if (candidate == uppermostNSCandidateID) { |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
1367 |
return m_namespaceDeclSets.get(wouldBeAt); |
6 | 1368 |
} |
1369 |
} |
|
1370 |
||
1371 |
while(wouldBeAt>=0 && ancestor>0) |
|
1372 |
{ |
|
1373 |
if (candidate==ancestor) { |
|
1374 |
// Found ancestor in list |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
1375 |
return m_namespaceDeclSets.get(wouldBeAt); |
6 | 1376 |
} else if (candidate<ancestor) { |
1377 |
// Too deep in tree |
|
1378 |
do { |
|
1379 |
ancestor=_parent(ancestor); |
|
1380 |
} while (candidate < ancestor); |
|
1381 |
} else if(wouldBeAt > 0){ |
|
1382 |
// Too late in list |
|
1383 |
candidate=m_namespaceDeclSetElements.elementAt(--wouldBeAt); |
|
1384 |
} |
|
1385 |
else |
|
1386 |
break; |
|
1387 |
} |
|
1388 |
} |
|
1389 |
||
1390 |
return null; // No namespaces known at this node |
|
1391 |
} |
|
1392 |
||
1393 |
/** |
|
1394 |
* Subroutine: Locate the specified node within |
|
1395 |
* m_namespaceDeclSetElements, or the last element which |
|
1396 |
* preceeds it in document order |
|
1397 |
* |
|
1398 |
* %REVIEW% Inlne this into findNamespaceContext? Create SortedSuballocatedIntVector type? |
|
1399 |
* |
|
1400 |
* @return If positive or zero, the index of the found item. |
|
1401 |
* If negative, index of the point at which it would have appeared, |
|
1402 |
* encoded as -1-index and hence reconvertable by subtracting |
|
1403 |
* it from -1. (Encoding because I don't want to recompare the strings |
|
1404 |
* but don't want to burn bytes on a datatype to hold a flagged value.) |
|
1405 |
*/ |
|
1406 |
protected int findInSortedSuballocatedIntVector(SuballocatedIntVector vector, int lookfor) |
|
1407 |
{ |
|
1408 |
// Binary search |
|
1409 |
int i = 0; |
|
1410 |
if(vector != null) { |
|
1411 |
int first = 0; |
|
1412 |
int last = vector.size() - 1; |
|
1413 |
||
1414 |
while (first <= last) { |
|
1415 |
i = (first + last) / 2; |
|
1416 |
int test = lookfor-vector.elementAt(i); |
|
1417 |
if(test == 0) { |
|
1418 |
return i; // Name found |
|
1419 |
} |
|
1420 |
else if (test < 0) { |
|
1421 |
last = i - 1; // looked too late |
|
1422 |
} |
|
1423 |
else { |
|
1424 |
first = i + 1; // looked ot early |
|
1425 |
} |
|
1426 |
} |
|
1427 |
||
1428 |
if (first > i) { |
|
1429 |
i = first; // Clean up at loop end |
|
1430 |
} |
|
1431 |
} |
|
1432 |
||
1433 |
return -1 - i; // not-found has to be encoded. |
|
1434 |
} |
|
1435 |
||
1436 |
||
1437 |
/** |
|
1438 |
* Given a node handle, get the index of the node's first child. |
|
1439 |
* If not yet resolved, waits for more nodes to be added to the document and |
|
1440 |
* tries again |
|
1441 |
* |
|
1442 |
* @param nodeHandle handle to node, which should probably be an element |
|
1443 |
* node, but need not be. |
|
1444 |
* |
|
1445 |
* @param inScope true if all namespaces in scope should be returned, |
|
1446 |
* false if only the namespace declarations should be |
|
1447 |
* returned. |
|
1448 |
* @return handle of first namespace, or DTM.NULL to indicate none exists. |
|
1449 |
*/ |
|
1450 |
public int getFirstNamespaceNode(int nodeHandle, boolean inScope) |
|
1451 |
{ |
|
1452 |
if(inScope) |
|
1453 |
{ |
|
1454 |
int identity = makeNodeIdentity(nodeHandle); |
|
1455 |
if (_type(identity) == DTM.ELEMENT_NODE) |
|
1456 |
{ |
|
1457 |
SuballocatedIntVector nsContext=findNamespaceContext(identity); |
|
1458 |
if(nsContext==null || nsContext.size()<1) |
|
1459 |
return NULL; |
|
1460 |
||
1461 |
return nsContext.elementAt(0); |
|
1462 |
} |
|
1463 |
else |
|
1464 |
return NULL; |
|
1465 |
} |
|
1466 |
else |
|
1467 |
{ |
|
1468 |
// Assume that attributes and namespaces immediately |
|
1469 |
// follow the element. |
|
1470 |
// |
|
1471 |
// %OPT% Would things be faster if all NS nodes were built |
|
1472 |
// before all Attr nodes? Some costs at build time for 2nd |
|
1473 |
// pass... |
|
1474 |
int identity = makeNodeIdentity(nodeHandle); |
|
1475 |
if (_type(identity) == DTM.ELEMENT_NODE) |
|
1476 |
{ |
|
1477 |
while (DTM.NULL != (identity = getNextNodeIdentity(identity))) |
|
1478 |
{ |
|
1479 |
int type = _type(identity); |
|
1480 |
if (type == DTM.NAMESPACE_NODE) |
|
1481 |
return makeNodeHandle(identity); |
|
1482 |
else if (DTM.ATTRIBUTE_NODE != type) |
|
1483 |
break; |
|
1484 |
} |
|
1485 |
return NULL; |
|
1486 |
} |
|
1487 |
else |
|
1488 |
return NULL; |
|
1489 |
} |
|
1490 |
} |
|
1491 |
||
1492 |
/** |
|
1493 |
* Given a namespace handle, advance to the next namespace. |
|
1494 |
* |
|
1495 |
* @param baseHandle handle to original node from where the first namespace |
|
1496 |
* was relative to (needed to return nodes in document order). |
|
1497 |
* @param nodeHandle A namespace handle for which we will find the next node. |
|
1498 |
* @param inScope true if all namespaces that are in scope should be processed, |
|
1499 |
* otherwise just process the nodes in the given element handle. |
|
1500 |
* @return handle of next namespace, or DTM.NULL to indicate none exists. |
|
1501 |
*/ |
|
1502 |
public int getNextNamespaceNode(int baseHandle, int nodeHandle, |
|
1503 |
boolean inScope) |
|
1504 |
{ |
|
1505 |
if(inScope) |
|
1506 |
{ |
|
1507 |
//Since we've been given the base, try direct lookup |
|
1508 |
//(could look from nodeHandle but this is at least one |
|
1509 |
//comparison/get-parent faster) |
|
1510 |
//SuballocatedIntVector nsContext=findNamespaceContext(nodeHandle & m_mask); |
|
1511 |
||
1512 |
SuballocatedIntVector nsContext=findNamespaceContext(makeNodeIdentity(baseHandle)); |
|
1513 |
||
1514 |
if(nsContext==null) |
|
1515 |
return NULL; |
|
1516 |
int i=1 + nsContext.indexOf(nodeHandle); |
|
1517 |
if(i<=0 || i==nsContext.size()) |
|
1518 |
return NULL; |
|
1519 |
||
1520 |
return nsContext.elementAt(i); |
|
1521 |
} |
|
1522 |
else |
|
1523 |
{ |
|
1524 |
// Assume that attributes and namespace nodes immediately follow the element. |
|
1525 |
int identity = makeNodeIdentity(nodeHandle); |
|
1526 |
while (DTM.NULL != (identity = getNextNodeIdentity(identity))) |
|
1527 |
{ |
|
1528 |
int type = _type(identity); |
|
1529 |
if (type == DTM.NAMESPACE_NODE) |
|
1530 |
{ |
|
1531 |
return makeNodeHandle(identity); |
|
1532 |
} |
|
1533 |
else if (type != DTM.ATTRIBUTE_NODE) |
|
1534 |
{ |
|
1535 |
break; |
|
1536 |
} |
|
1537 |
} |
|
1538 |
} |
|
1539 |
return DTM.NULL; |
|
1540 |
} |
|
1541 |
||
1542 |
/** |
|
1543 |
* Given a node handle, find its parent node. |
|
1544 |
* |
|
1545 |
* @param nodeHandle the id of the node. |
|
1546 |
* @return int Node-number of parent, |
|
1547 |
* or DTM.NULL to indicate none exists. |
|
1548 |
*/ |
|
1549 |
public int getParent(int nodeHandle) |
|
1550 |
{ |
|
1551 |
||
1552 |
int identity = makeNodeIdentity(nodeHandle); |
|
1553 |
||
1554 |
if (identity > 0) |
|
1555 |
return makeNodeHandle(_parent(identity)); |
|
1556 |
else |
|
1557 |
return DTM.NULL; |
|
1558 |
} |
|
1559 |
||
1560 |
/** |
|
1561 |
* Find the Document node handle for the document currently under construction. |
|
1562 |
* PLEASE NOTE that most people should use getOwnerDocument(nodeHandle) instead; |
|
1563 |
* this version of the operation is primarily intended for use during negotiation |
|
1564 |
* with the DTM Manager. |
|
1565 |
* |
|
1566 |
* @return int Node handle of document, which should always be valid. |
|
1567 |
*/ |
|
1568 |
public int getDocument() |
|
1569 |
{ |
|
1570 |
return m_dtmIdent.elementAt(0); // makeNodeHandle(0) |
|
1571 |
} |
|
1572 |
||
1573 |
/** |
|
1574 |
* Given a node handle, find the owning document node. This has the exact |
|
1575 |
* same semantics as the DOM Document method of the same name, in that if |
|
1576 |
* the nodeHandle is a document node, it will return NULL. |
|
1577 |
* |
|
1578 |
* <p>%REVIEW% Since this is DOM-specific, it may belong at the DOM |
|
1579 |
* binding layer. Included here as a convenience function and to |
|
1580 |
* aid porting of DOM code to DTM.</p> |
|
1581 |
* |
|
1582 |
* @param nodeHandle the id of the node. |
|
1583 |
* @return int Node handle of owning document, or -1 if the node was a Docment |
|
1584 |
*/ |
|
1585 |
public int getOwnerDocument(int nodeHandle) |
|
1586 |
{ |
|
1587 |
||
1588 |
if (DTM.DOCUMENT_NODE == getNodeType(nodeHandle)) |
|
1589 |
return DTM.NULL; |
|
1590 |
||
1591 |
return getDocumentRoot(nodeHandle); |
|
1592 |
} |
|
1593 |
||
1594 |
/** |
|
1595 |
* Given a node handle, find the owning document node. Unlike the DOM, |
|
1596 |
* this considers the owningDocument of a Document to be itself. |
|
1597 |
* |
|
1598 |
* @param nodeHandle the id of the node. |
|
1599 |
* @return int Node handle of owning document, or the nodeHandle if it is |
|
1600 |
* a Document. |
|
1601 |
*/ |
|
1602 |
public int getDocumentRoot(int nodeHandle) |
|
1603 |
{ |
|
1604 |
return getManager().getDTM(nodeHandle).getDocument(); |
|
1605 |
} |
|
1606 |
||
1607 |
/** |
|
1608 |
* Get the string-value of a node as a String object |
|
1609 |
* (see http://www.w3.org/TR/xpath#data-model |
|
1610 |
* for the definition of a node's string-value). |
|
1611 |
* |
|
1612 |
* @param nodeHandle The node ID. |
|
1613 |
* |
|
1614 |
* @return A string object that represents the string-value of the given node. |
|
1615 |
*/ |
|
1616 |
public abstract XMLString getStringValue(int nodeHandle); |
|
1617 |
||
1618 |
/** |
|
1619 |
* Get number of character array chunks in |
|
1620 |
* the string-value of a node. |
|
1621 |
* (see http://www.w3.org/TR/xpath#data-model |
|
1622 |
* for the definition of a node's string-value). |
|
1623 |
* Note that a single text node may have multiple text chunks. |
|
1624 |
* |
|
1625 |
* @param nodeHandle The node ID. |
|
1626 |
* |
|
1627 |
* @return number of character array chunks in |
|
1628 |
* the string-value of a node. |
|
1629 |
*/ |
|
1630 |
public int getStringValueChunkCount(int nodeHandle) |
|
1631 |
{ |
|
1632 |
||
1633 |
// %TBD% |
|
1634 |
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//("getStringValueChunkCount not yet supported!"); |
|
1635 |
||
1636 |
return 0; |
|
1637 |
} |
|
1638 |
||
1639 |
/** |
|
1640 |
* Get a character array chunk in the string-value of a node. |
|
1641 |
* (see http://www.w3.org/TR/xpath#data-model |
|
1642 |
* for the definition of a node's string-value). |
|
1643 |
* Note that a single text node may have multiple text chunks. |
|
1644 |
* |
|
1645 |
* @param nodeHandle The node ID. |
|
1646 |
* @param chunkIndex Which chunk to get. |
|
1647 |
* @param startAndLen An array of 2 where the start position and length of |
|
1648 |
* the chunk will be returned. |
|
1649 |
* |
|
1650 |
* @return The character array reference where the chunk occurs. |
|
1651 |
*/ |
|
1652 |
public char[] getStringValueChunk(int nodeHandle, int chunkIndex, |
|
1653 |
int[] startAndLen) |
|
1654 |
{ |
|
1655 |
||
1656 |
// %TBD% |
|
1657 |
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"getStringValueChunk not yet supported!"); |
|
1658 |
||
1659 |
return null; |
|
1660 |
} |
|
1661 |
||
1662 |
/** |
|
1663 |
* Given a node handle, return an ID that represents the node's expanded name. |
|
1664 |
* |
|
1665 |
* @param nodeHandle The handle to the node in question. |
|
1666 |
* |
|
1667 |
* @return the expanded-name id of the node. |
|
1668 |
*/ |
|
1669 |
public int getExpandedTypeID(int nodeHandle) |
|
1670 |
{ |
|
1671 |
// %REVIEW% This _should_ only be null if someone asked the wrong DTM about the node... |
|
1672 |
// which one would hope would never happen... |
|
1673 |
int id=makeNodeIdentity(nodeHandle); |
|
1674 |
if(id==NULL) |
|
1675 |
return NULL; |
|
1676 |
return _exptype(id); |
|
1677 |
} |
|
1678 |
||
1679 |
/** |
|
1680 |
* Given an expanded name, return an ID. If the expanded-name does not |
|
1681 |
* exist in the internal tables, the entry will be created, and the ID will |
|
1682 |
* be returned. Any additional nodes that are created that have this |
|
1683 |
* expanded name will use this ID. |
|
1684 |
* |
|
1685 |
* @param type The simple type, i.e. one of ELEMENT, ATTRIBUTE, etc. |
|
1686 |
* |
|
1687 |
* @param namespace The namespace URI, which may be null, may be an empty |
|
1688 |
* string (which will be the same as null), or may be a |
|
1689 |
* namespace URI. |
|
1690 |
* @param localName The local name string, which must be a valid |
|
1691 |
* <a href="http://www.w3.org/TR/REC-xml-names/">NCName</a>. |
|
1692 |
* |
|
1693 |
* @return the expanded-name id of the node. |
|
1694 |
*/ |
|
1695 |
public int getExpandedTypeID(String namespace, String localName, int type) |
|
1696 |
{ |
|
1697 |
||
1698 |
ExpandedNameTable ent = m_expandedNameTable; |
|
1699 |
||
1700 |
return ent.getExpandedTypeID(namespace, localName, type); |
|
1701 |
} |
|
1702 |
||
1703 |
/** |
|
1704 |
* Given an expanded-name ID, return the local name part. |
|
1705 |
* |
|
1706 |
* @param expandedNameID an ID that represents an expanded-name. |
|
1707 |
* @return String Local name of this node. |
|
1708 |
*/ |
|
1709 |
public String getLocalNameFromExpandedNameID(int expandedNameID) |
|
1710 |
{ |
|
1711 |
return m_expandedNameTable.getLocalName(expandedNameID); |
|
1712 |
} |
|
1713 |
||
1714 |
/** |
|
1715 |
* Given an expanded-name ID, return the namespace URI part. |
|
1716 |
* |
|
1717 |
* @param expandedNameID an ID that represents an expanded-name. |
|
1718 |
* @return String URI value of this node's namespace, or null if no |
|
1719 |
* namespace was resolved. |
|
1720 |
*/ |
|
1721 |
public String getNamespaceFromExpandedNameID(int expandedNameID) |
|
1722 |
{ |
|
1723 |
return m_expandedNameTable.getNamespace(expandedNameID); |
|
1724 |
} |
|
1725 |
||
1726 |
/** |
|
1727 |
* Returns the namespace type of a specific node |
|
1728 |
* @param nodeHandle the id of the node. |
|
1729 |
* @return the ID of the namespace. |
|
1730 |
*/ |
|
1731 |
public int getNamespaceType(final int nodeHandle) |
|
1732 |
{ |
|
1733 |
||
1734 |
int identity = makeNodeIdentity(nodeHandle); |
|
1735 |
int expandedNameID = _exptype(identity); |
|
1736 |
||
1737 |
return m_expandedNameTable.getNamespaceID(expandedNameID); |
|
1738 |
} |
|
1739 |
||
1740 |
/** |
|
1741 |
* Given a node handle, return its DOM-style node name. This will |
|
1742 |
* include names such as #text or #document. |
|
1743 |
* |
|
1744 |
* @param nodeHandle the id of the node. |
|
1745 |
* @return String Name of this node, which may be an empty string. |
|
1746 |
* %REVIEW% Document when empty string is possible... |
|
1747 |
* %REVIEW-COMMENT% It should never be empty, should it? |
|
1748 |
*/ |
|
1749 |
public abstract String getNodeName(int nodeHandle); |
|
1750 |
||
1751 |
/** |
|
1752 |
* Given a node handle, return the XPath node name. This should be |
|
1753 |
* the name as described by the XPath data model, NOT the DOM-style |
|
1754 |
* name. |
|
1755 |
* |
|
1756 |
* @param nodeHandle the id of the node. |
|
1757 |
* @return String Name of this node, which may be an empty string. |
|
1758 |
*/ |
|
1759 |
public String getNodeNameX(int nodeHandle) |
|
1760 |
{ |
|
1761 |
||
1762 |
/** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */ |
|
1763 |
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!"); |
|
1764 |
||
1765 |
return null; |
|
1766 |
} |
|
1767 |
||
1768 |
/** |
|
1769 |
* Given a node handle, return its XPath-style localname. |
|
1770 |
* (As defined in Namespaces, this is the portion of the name after any |
|
1771 |
* colon character). |
|
1772 |
* |
|
1773 |
* @param nodeHandle the id of the node. |
|
1774 |
* @return String Local name of this node. |
|
1775 |
*/ |
|
1776 |
public abstract String getLocalName(int nodeHandle); |
|
1777 |
||
1778 |
/** |
|
1779 |
* Given a namespace handle, return the prefix that the namespace decl is |
|
1780 |
* mapping. |
|
1781 |
* Given a node handle, return the prefix used to map to the namespace. |
|
1782 |
* |
|
1783 |
* <p> %REVIEW% Are you sure you want "" for no prefix? </p> |
|
1784 |
* <p> %REVIEW-COMMENT% I think so... not totally sure. -sb </p> |
|
1785 |
* |
|
1786 |
* @param nodeHandle the id of the node. |
|
1787 |
* @return String prefix of this node's name, or "" if no explicit |
|
1788 |
* namespace prefix was given. |
|
1789 |
*/ |
|
1790 |
public abstract String getPrefix(int nodeHandle); |
|
1791 |
||
1792 |
/** |
|
1793 |
* Given a node handle, return its DOM-style namespace URI |
|
1794 |
* (As defined in Namespaces, this is the declared URI which this node's |
|
1795 |
* prefix -- or default in lieu thereof -- was mapped to.) |
|
1796 |
* |
|
1797 |
* <p>%REVIEW% Null or ""? -sb</p> |
|
1798 |
* |
|
1799 |
* @param nodeHandle the id of the node. |
|
1800 |
* @return String URI value of this node's namespace, or null if no |
|
1801 |
* namespace was resolved. |
|
1802 |
*/ |
|
1803 |
public abstract String getNamespaceURI(int nodeHandle); |
|
1804 |
||
1805 |
/** |
|
1806 |
* Given a node handle, return its node value. This is mostly |
|
1807 |
* as defined by the DOM, but may ignore some conveniences. |
|
1808 |
* <p> |
|
1809 |
* |
|
1810 |
* @param nodeHandle The node id. |
|
1811 |
* @return String Value of this node, or null if not |
|
1812 |
* meaningful for this node type. |
|
1813 |
*/ |
|
1814 |
public abstract String getNodeValue(int nodeHandle); |
|
1815 |
||
1816 |
/** |
|
1817 |
* Given a node handle, return its DOM-style node type. |
|
1818 |
* <p> |
|
1819 |
* %REVIEW% Generally, returning short is false economy. Return int? |
|
1820 |
* %REVIEW% Make assumption that node has already arrived. Is OK? |
|
1821 |
* |
|
1822 |
* @param nodeHandle The node id. |
|
1823 |
* @return int Node type, as per the DOM's Node._NODE constants. |
|
1824 |
*/ |
|
1825 |
public short getNodeType(int nodeHandle) |
|
1826 |
{ |
|
1827 |
if (nodeHandle == DTM.NULL) |
|
1828 |
return DTM.NULL; |
|
1829 |
return m_expandedNameTable.getType(_exptype(makeNodeIdentity(nodeHandle))); |
|
1830 |
} |
|
1831 |
||
1832 |
/** |
|
1833 |
* Get the depth level of this node in the tree (equals 1 for |
|
1834 |
* a parentless node). |
|
1835 |
* |
|
1836 |
* @param nodeHandle The node id. |
|
1837 |
* @return the number of ancestors, plus one |
|
1838 |
* @xsl.usage internal |
|
1839 |
*/ |
|
1840 |
public short getLevel(int nodeHandle) |
|
1841 |
{ |
|
1842 |
// Apparently, the axis walker stuff requires levels to count from 1. |
|
1843 |
int identity = makeNodeIdentity(nodeHandle); |
|
1844 |
return (short) (_level(identity) + 1); |
|
1845 |
} |
|
1846 |
||
1847 |
/** |
|
1848 |
* Get the identity of this node in the tree |
|
1849 |
* |
|
1850 |
* @param nodeHandle The node handle. |
|
1851 |
* @return the node identity |
|
1852 |
* @xsl.usage internal |
|
1853 |
*/ |
|
1854 |
public int getNodeIdent(int nodeHandle) |
|
1855 |
{ |
|
1856 |
/*if (nodeHandle != DTM.NULL) |
|
1857 |
return nodeHandle & m_mask; |
|
1858 |
else |
|
1859 |
return DTM.NULL;*/ |
|
1860 |
||
1861 |
return makeNodeIdentity(nodeHandle); |
|
1862 |
} |
|
1863 |
||
1864 |
/** |
|
1865 |
* Get the handle of this node in the tree |
|
1866 |
* |
|
1867 |
* @param nodeId The node identity. |
|
1868 |
* @return the node handle |
|
1869 |
* @xsl.usage internal |
|
1870 |
*/ |
|
1871 |
public int getNodeHandle(int nodeId) |
|
1872 |
{ |
|
1873 |
/*if (nodeId != DTM.NULL) |
|
1874 |
return nodeId | m_dtmIdent; |
|
1875 |
else |
|
1876 |
return DTM.NULL;*/ |
|
1877 |
||
1878 |
return makeNodeHandle(nodeId); |
|
1879 |
} |
|
1880 |
||
1881 |
// ============== Document query functions ============== |
|
1882 |
||
1883 |
/** |
|
1884 |
* Tests whether DTM DOM implementation implements a specific feature and |
|
1885 |
* that feature is supported by this node. |
|
1886 |
* |
|
1887 |
* @param feature The name of the feature to test. |
|
1888 |
* @param version This is the version number of the feature to test. |
|
1889 |
* If the version is not |
|
1890 |
* specified, supporting any version of the feature will cause the |
|
1891 |
* method to return <code>true</code>. |
|
1892 |
* @return Returns <code>true</code> if the specified feature is |
|
1893 |
* supported on this node, <code>false</code> otherwise. |
|
1894 |
*/ |
|
1895 |
public boolean isSupported(String feature, String version) |
|
1896 |
{ |
|
1897 |
||
1898 |
// %TBD% |
|
1899 |
return false; |
|
1900 |
} |
|
1901 |
||
1902 |
/** |
|
1903 |
* Return the base URI of the document entity. If it is not known |
|
1904 |
* (because the document was parsed from a socket connection or from |
|
1905 |
* standard input, for example), the value of this property is unknown. |
|
1906 |
* |
|
1907 |
* @return the document base URI String object or null if unknown. |
|
1908 |
*/ |
|
1909 |
public String getDocumentBaseURI() |
|
1910 |
{ |
|
1911 |
return m_documentBaseURI; |
|
1912 |
} |
|
1913 |
||
1914 |
/** |
|
1915 |
* Set the base URI of the document entity. |
|
1916 |
* |
|
1917 |
* @param baseURI the document base URI String object or null if unknown. |
|
1918 |
*/ |
|
1919 |
public void setDocumentBaseURI(String baseURI) |
|
1920 |
{ |
|
1921 |
m_documentBaseURI = baseURI; |
|
1922 |
} |
|
1923 |
||
1924 |
/** |
|
1925 |
* Return the system identifier of the document entity. If |
|
1926 |
* it is not known, the value of this property is unknown. |
|
1927 |
* |
|
1928 |
* @param nodeHandle The node id, which can be any valid node handle. |
|
1929 |
* @return the system identifier String object or null if unknown. |
|
1930 |
*/ |
|
1931 |
public String getDocumentSystemIdentifier(int nodeHandle) |
|
1932 |
{ |
|
1933 |
||
1934 |
// %REVIEW% OK? -sb |
|
1935 |
return m_documentBaseURI; |
|
1936 |
} |
|
1937 |
||
1938 |
/** |
|
1939 |
* Return the name of the character encoding scheme |
|
1940 |
* in which the document entity is expressed. |
|
1941 |
* |
|
1942 |
* @param nodeHandle The node id, which can be any valid node handle. |
|
1943 |
* @return the document encoding String object. |
|
1944 |
* @xsl.usage internal |
|
1945 |
*/ |
|
1946 |
public String getDocumentEncoding(int nodeHandle) |
|
1947 |
{ |
|
1948 |
||
1949 |
// %REVIEW% OK?? -sb |
|
1950 |
return "UTF-8"; |
|
1951 |
} |
|
1952 |
||
1953 |
/** |
|
1954 |
* Return an indication of the standalone status of the document, |
|
1955 |
* either "yes" or "no". This property is derived from the optional |
|
1956 |
* standalone document declaration in the XML declaration at the |
|
1957 |
* beginning of the document entity, and has no value if there is no |
|
1958 |
* standalone document declaration. |
|
1959 |
* |
|
1960 |
* @param nodeHandle The node id, which can be any valid node handle. |
|
1961 |
* @return the document standalone String object, either "yes", "no", or null. |
|
1962 |
*/ |
|
1963 |
public String getDocumentStandalone(int nodeHandle) |
|
1964 |
{ |
|
1965 |
return null; |
|
1966 |
} |
|
1967 |
||
1968 |
/** |
|
1969 |
* Return a string representing the XML version of the document. This |
|
1970 |
* property is derived from the XML declaration optionally present at the |
|
1971 |
* beginning of the document entity, and has no value if there is no XML |
|
1972 |
* declaration. |
|
1973 |
* |
|
1974 |
* @param documentHandle The document handle |
|
1975 |
* |
|
1976 |
* @return the document version String object. |
|
1977 |
*/ |
|
1978 |
public String getDocumentVersion(int documentHandle) |
|
1979 |
{ |
|
1980 |
return null; |
|
1981 |
} |
|
1982 |
||
1983 |
/** |
|
1984 |
* Return an indication of |
|
1985 |
* whether the processor has read the complete DTD. Its value is a |
|
1986 |
* boolean. If it is false, then certain properties (indicated in their |
|
1987 |
* descriptions below) may be unknown. If it is true, those properties |
|
1988 |
* are never unknown. |
|
1989 |
* |
|
1990 |
* @return <code>true</code> if all declarations were processed; |
|
1991 |
* <code>false</code> otherwise. |
|
1992 |
*/ |
|
1993 |
public boolean getDocumentAllDeclarationsProcessed() |
|
1994 |
{ |
|
1995 |
||
1996 |
// %REVIEW% OK? |
|
1997 |
return true; |
|
1998 |
} |
|
1999 |
||
2000 |
/** |
|
2001 |
* A document type declaration information item has the following properties: |
|
2002 |
* |
|
2003 |
* 1. [system identifier] The system identifier of the external subset, if |
|
2004 |
* it exists. Otherwise this property has no value. |
|
2005 |
* |
|
2006 |
* @return the system identifier String object, or null if there is none. |
|
2007 |
*/ |
|
2008 |
public abstract String getDocumentTypeDeclarationSystemIdentifier(); |
|
2009 |
||
2010 |
/** |
|
2011 |
* Return the public identifier of the external subset, |
|
2012 |
* normalized as described in 4.2.2 External Entities [XML]. If there is |
|
2013 |
* no external subset or if it has no public identifier, this property |
|
2014 |
* has no value. |
|
2015 |
* |
|
2016 |
* @return the public identifier String object, or null if there is none. |
|
2017 |
*/ |
|
2018 |
public abstract String getDocumentTypeDeclarationPublicIdentifier(); |
|
2019 |
||
2020 |
/** |
|
2021 |
* Returns the <code>Element</code> whose <code>ID</code> is given by |
|
2022 |
* <code>elementId</code>. If no such element exists, returns |
|
2023 |
* <code>DTM.NULL</code>. Behavior is not defined if more than one element |
|
2024 |
* has this <code>ID</code>. Attributes (including those |
|
2025 |
* with the name "ID") are not of type ID unless so defined by DTD/Schema |
|
2026 |
* information available to the DTM implementation. |
|
2027 |
* Implementations that do not know whether attributes are of type ID or |
|
2028 |
* not are expected to return <code>DTM.NULL</code>. |
|
2029 |
* |
|
2030 |
* <p>%REVIEW% Presumably IDs are still scoped to a single document, |
|
2031 |
* and this operation searches only within a single document, right? |
|
2032 |
* Wouldn't want collisions between DTMs in the same process.</p> |
|
2033 |
* |
|
2034 |
* @param elementId The unique <code>id</code> value for an element. |
|
2035 |
* @return The handle of the matching element. |
|
2036 |
*/ |
|
2037 |
public abstract int getElementById(String elementId); |
|
2038 |
||
2039 |
/** |
|
2040 |
* The getUnparsedEntityURI function returns the URI of the unparsed |
|
2041 |
* entity with the specified name in the same document as the context |
|
2042 |
* node (see [3.3 Unparsed Entities]). It returns the empty string if |
|
2043 |
* there is no such entity. |
|
2044 |
* <p> |
|
2045 |
* XML processors may choose to use the System Identifier (if one |
|
2046 |
* is provided) to resolve the entity, rather than the URI in the |
|
2047 |
* Public Identifier. The details are dependent on the processor, and |
|
2048 |
* we would have to support some form of plug-in resolver to handle |
|
2049 |
* this properly. Currently, we simply return the System Identifier if |
|
2050 |
* present, and hope that it a usable URI or that our caller can |
|
2051 |
* map it to one. |
|
2052 |
* TODO: Resolve Public Identifiers... or consider changing function name. |
|
2053 |
* <p> |
|
2054 |
* If we find a relative URI |
|
2055 |
* reference, XML expects it to be resolved in terms of the base URI |
|
2056 |
* of the document. The DOM doesn't do that for us, and it isn't |
|
2057 |
* entirely clear whether that should be done here; currently that's |
|
2058 |
* pushed up to a higher level of our application. (Note that DOM Level |
|
2059 |
* 1 didn't store the document's base URI.) |
|
2060 |
* TODO: Consider resolving Relative URIs. |
|
2061 |
* <p> |
|
2062 |
* (The DOM's statement that "An XML processor may choose to |
|
2063 |
* completely expand entities before the structure model is passed |
|
2064 |
* to the DOM" refers only to parsed entities, not unparsed, and hence |
|
2065 |
* doesn't affect this function.) |
|
2066 |
* |
|
2067 |
* @param name A string containing the Entity Name of the unparsed |
|
2068 |
* entity. |
|
2069 |
* |
|
2070 |
* @return String containing the URI of the Unparsed Entity, or an |
|
2071 |
* empty string if no such entity exists. |
|
2072 |
*/ |
|
2073 |
public abstract String getUnparsedEntityURI(String name); |
|
2074 |
||
2075 |
// ============== Boolean methods ================ |
|
2076 |
||
2077 |
/** |
|
2078 |
* Return true if the xsl:strip-space or xsl:preserve-space was processed |
|
2079 |
* during construction of the DTM document. |
|
2080 |
* |
|
2081 |
* @return true if this DTM supports prestripping. |
|
2082 |
*/ |
|
2083 |
public boolean supportsPreStripping() |
|
2084 |
{ |
|
2085 |
return true; |
|
2086 |
} |
|
2087 |
||
2088 |
/** |
|
2089 |
* Figure out whether nodeHandle2 should be considered as being later |
|
2090 |
* in the document than nodeHandle1, in Document Order as defined |
|
2091 |
* by the XPath model. This may not agree with the ordering defined |
|
2092 |
* by other XML applications. |
|
2093 |
* <p> |
|
2094 |
* There are some cases where ordering isn't defined, and neither are |
|
2095 |
* the results of this function -- though we'll generally return false. |
|
2096 |
* |
|
2097 |
* @param nodeHandle1 Node handle to perform position comparison on. |
|
2098 |
* @param nodeHandle2 Second Node handle to perform position comparison on . |
|
2099 |
* |
|
2100 |
* @return true if node1 comes before node2, otherwise return false. |
|
2101 |
* You can think of this as |
|
2102 |
* <code>(node1.documentOrderPosition <= node2.documentOrderPosition)</code>. |
|
2103 |
*/ |
|
2104 |
public boolean isNodeAfter(int nodeHandle1, int nodeHandle2) |
|
2105 |
{ |
|
2106 |
// These return NULL if the node doesn't belong to this document. |
|
2107 |
int index1 = makeNodeIdentity(nodeHandle1); |
|
2108 |
int index2 = makeNodeIdentity(nodeHandle2); |
|
2109 |
||
2110 |
return index1!=NULL && index2!=NULL && index1 <= index2; |
|
2111 |
} |
|
2112 |
||
2113 |
/** |
|
2114 |
* 2. [element content whitespace] A boolean indicating whether the |
|
2115 |
* character is white space appearing within element content (see [XML], |
|
2116 |
* 2.10 "White Space Handling"). Note that validating XML processors are |
|
2117 |
* required by XML 1.0 to provide this information. If there is no |
|
2118 |
* declaration for the containing element, this property has no value for |
|
2119 |
* white space characters. If no declaration has been read, but the [all |
|
2120 |
* declarations processed] property of the document information item is |
|
2121 |
* false (so there may be an unread declaration), then the value of this |
|
2122 |
* property is unknown for white space characters. It is always false for |
|
2123 |
* characters that are not white space. |
|
2124 |
* |
|
2125 |
* @param nodeHandle the node ID. |
|
2126 |
* @return <code>true</code> if the character data is whitespace; |
|
2127 |
* <code>false</code> otherwise. |
|
2128 |
*/ |
|
2129 |
public boolean isCharacterElementContentWhitespace(int nodeHandle) |
|
2130 |
{ |
|
2131 |
||
2132 |
// %TBD% |
|
2133 |
return false; |
|
2134 |
} |
|
2135 |
||
2136 |
/** |
|
2137 |
* 10. [all declarations processed] This property is not strictly speaking |
|
2138 |
* part of the infoset of the document. Rather it is an indication of |
|
2139 |
* whether the processor has read the complete DTD. Its value is a |
|
2140 |
* boolean. If it is false, then certain properties (indicated in their |
|
2141 |
* descriptions below) may be unknown. If it is true, those properties |
|
2142 |
* are never unknown. |
|
2143 |
* |
|
2144 |
* @param documentHandle A node handle that must identify a document. |
|
2145 |
* @return <code>true</code> if all declarations were processed; |
|
2146 |
* <code>false</code> otherwise. |
|
2147 |
*/ |
|
2148 |
public boolean isDocumentAllDeclarationsProcessed(int documentHandle) |
|
2149 |
{ |
|
2150 |
return true; |
|
2151 |
} |
|
2152 |
||
2153 |
/** |
|
2154 |
* 5. [specified] A flag indicating whether this attribute was actually |
|
2155 |
* specified in the start-tag of its element, or was defaulted from the |
|
2156 |
* DTD. |
|
2157 |
* |
|
2158 |
* @param attributeHandle The attribute handle in question. |
|
2159 |
* |
|
2160 |
* @return <code>true</code> if the attribute was specified; |
|
2161 |
* <code>false</code> if it was defaulted. |
|
2162 |
*/ |
|
2163 |
public abstract boolean isAttributeSpecified(int attributeHandle); |
|
2164 |
||
2165 |
// ========== Direct SAX Dispatch, for optimization purposes ======== |
|
2166 |
||
2167 |
/** |
|
2168 |
* Directly call the |
|
2169 |
* characters method on the passed ContentHandler for the |
|
2170 |
* string-value of the given node (see http://www.w3.org/TR/xpath#data-model |
|
2171 |
* for the definition of a node's string-value). Multiple calls to the |
|
2172 |
* ContentHandler's characters methods may well occur for a single call to |
|
2173 |
* this method. |
|
2174 |
* |
|
2175 |
* @param nodeHandle The node ID. |
|
2176 |
* @param ch A non-null reference to a ContentHandler. |
|
2177 |
* @param normalize true if the content should be normalized according to |
|
2178 |
* the rules for the XPath |
|
2179 |
* <a href="http://www.w3.org/TR/xpath#function-normalize-space">normalize-space</a> |
|
2180 |
* function. |
|
2181 |
* |
|
2182 |
* @throws org.xml.sax.SAXException |
|
2183 |
*/ |
|
2184 |
public abstract void dispatchCharactersEvents( |
|
2185 |
int nodeHandle, org.xml.sax.ContentHandler ch, boolean normalize) |
|
2186 |
throws org.xml.sax.SAXException; |
|
2187 |
||
2188 |
/** |
|
2189 |
* Directly create SAX parser events from a subtree. |
|
2190 |
* |
|
2191 |
* @param nodeHandle The node ID. |
|
2192 |
* @param ch A non-null reference to a ContentHandler. |
|
2193 |
* |
|
2194 |
* @throws org.xml.sax.SAXException |
|
2195 |
*/ |
|
2196 |
public abstract void dispatchToEvents( |
|
2197 |
int nodeHandle, org.xml.sax.ContentHandler ch) |
|
2198 |
throws org.xml.sax.SAXException; |
|
2199 |
||
2200 |
/** |
|
2201 |
* Return an DOM node for the given node. |
|
2202 |
* |
|
2203 |
* @param nodeHandle The node ID. |
|
2204 |
* |
|
2205 |
* @return A node representation of the DTM node. |
|
2206 |
*/ |
|
2207 |
public org.w3c.dom.Node getNode(int nodeHandle) |
|
2208 |
{ |
|
2209 |
return new DTMNodeProxy(this, nodeHandle); |
|
2210 |
} |
|
2211 |
||
2212 |
// ==== Construction methods (may not be supported by some implementations!) ===== |
|
2213 |
||
2214 |
/** |
|
2215 |
* Append a child to the end of the document. Please note that the node |
|
2216 |
* is always cloned if it is owned by another document. |
|
2217 |
* |
|
2218 |
* <p>%REVIEW% "End of the document" needs to be defined more clearly. |
|
2219 |
* Does it become the last child of the Document? Of the root element?</p> |
|
2220 |
* |
|
2221 |
* @param newChild Must be a valid new node handle. |
|
2222 |
* @param clone true if the child should be cloned into the document. |
|
2223 |
* @param cloneDepth if the clone argument is true, specifies that the |
|
2224 |
* clone should include all it's children. |
|
2225 |
*/ |
|
2226 |
public void appendChild(int newChild, boolean clone, boolean cloneDepth) |
|
2227 |
{ |
|
2228 |
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"appendChild not yet supported!"); |
|
2229 |
} |
|
2230 |
||
2231 |
/** |
|
2232 |
* Append a text node child that will be constructed from a string, |
|
2233 |
* to the end of the document. |
|
2234 |
* |
|
2235 |
* <p>%REVIEW% "End of the document" needs to be defined more clearly. |
|
2236 |
* Does it become the last child of the Document? Of the root element?</p> |
|
2237 |
* |
|
2238 |
* @param str Non-null reverence to a string. |
|
2239 |
*/ |
|
2240 |
public void appendTextChild(String str) |
|
2241 |
{ |
|
2242 |
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"appendTextChild not yet supported!"); |
|
2243 |
} |
|
2244 |
||
2245 |
/** |
|
2246 |
* Simple error for asserts and the like. |
|
2247 |
* |
|
2248 |
* @param msg Error message to report. |
|
2249 |
*/ |
|
2250 |
protected void error(String msg) |
|
2251 |
{ |
|
2252 |
throw new DTMException(msg); |
|
2253 |
} |
|
2254 |
||
2255 |
/** |
|
2256 |
* Find out whether or not to strip whispace nodes. |
|
2257 |
* |
|
2258 |
* |
|
2259 |
* @return whether or not to strip whispace nodes. |
|
2260 |
*/ |
|
2261 |
protected boolean getShouldStripWhitespace() |
|
2262 |
{ |
|
2263 |
return m_shouldStripWS; |
|
2264 |
} |
|
2265 |
||
2266 |
/** |
|
2267 |
* Set whether to strip whitespaces and push in current value of |
|
2268 |
* m_shouldStripWS in m_shouldStripWhitespaceStack. |
|
2269 |
* |
|
2270 |
* @param shouldStrip Flag indicating whether to strip whitespace nodes |
|
2271 |
*/ |
|
2272 |
protected void pushShouldStripWhitespace(boolean shouldStrip) |
|
2273 |
{ |
|
2274 |
||
2275 |
m_shouldStripWS = shouldStrip; |
|
2276 |
||
2277 |
if (null != m_shouldStripWhitespaceStack) |
|
2278 |
m_shouldStripWhitespaceStack.push(shouldStrip); |
|
2279 |
} |
|
2280 |
||
2281 |
/** |
|
2282 |
* Set whether to strip whitespaces at this point by popping out |
|
2283 |
* m_shouldStripWhitespaceStack. |
|
2284 |
* |
|
2285 |
*/ |
|
2286 |
protected void popShouldStripWhitespace() |
|
2287 |
{ |
|
2288 |
if (null != m_shouldStripWhitespaceStack) |
|
2289 |
m_shouldStripWS = m_shouldStripWhitespaceStack.popAndTop(); |
|
2290 |
} |
|
2291 |
||
2292 |
/** |
|
2293 |
* Set whether to strip whitespaces and set the top of the stack to |
|
2294 |
* the current value of m_shouldStripWS. |
|
2295 |
* |
|
2296 |
* |
|
2297 |
* @param shouldStrip Flag indicating whether to strip whitespace nodes |
|
2298 |
*/ |
|
2299 |
protected void setShouldStripWhitespace(boolean shouldStrip) |
|
2300 |
{ |
|
2301 |
||
2302 |
m_shouldStripWS = shouldStrip; |
|
2303 |
||
2304 |
if (null != m_shouldStripWhitespaceStack) |
|
2305 |
m_shouldStripWhitespaceStack.setTop(shouldStrip); |
|
2306 |
} |
|
2307 |
||
2308 |
/** |
|
2309 |
* A dummy routine to satisify the abstract interface. If the DTM |
|
2310 |
* implememtation that extends the default base requires notification |
|
2311 |
* of registration, they can override this method. |
|
2312 |
*/ |
|
2313 |
public void documentRegistration() |
|
2314 |
{ |
|
2315 |
} |
|
2316 |
||
2317 |
/** |
|
2318 |
* A dummy routine to satisify the abstract interface. If the DTM |
|
2319 |
* implememtation that extends the default base requires notification |
|
2320 |
* when the document is being released, they can override this method |
|
2321 |
*/ |
|
2322 |
public void documentRelease() |
|
2323 |
{ |
|
2324 |
} |
|
2325 |
||
2326 |
/** |
|
2327 |
* Migrate a DTM built with an old DTMManager to a new DTMManager. |
|
2328 |
* After the migration, the new DTMManager will treat the DTM as |
|
2329 |
* one that is built by itself. |
|
2330 |
* This is used to support DTM sharing between multiple transformations. |
|
2331 |
* @param mgr the DTMManager |
|
2332 |
*/ |
|
2333 |
public void migrateTo(DTMManager mgr) |
|
2334 |
{ |
|
2335 |
m_mgr = mgr; |
|
2336 |
if(mgr instanceof DTMManagerDefault) |
|
2337 |
m_mgrDefault=(DTMManagerDefault)mgr; |
|
2338 |
} |
|
2339 |
||
2340 |
/** Query which DTMManager this DTM is currently being handled by. |
|
2341 |
* |
|
2342 |
* %REVEW% Should this become part of the base DTM API? |
|
2343 |
* |
|
2344 |
* @return a DTMManager, or null if this is a "stand-alone" DTM. |
|
2345 |
*/ |
|
2346 |
public DTMManager getManager() |
|
2347 |
{ |
|
2348 |
return m_mgr; |
|
2349 |
} |
|
2350 |
||
2351 |
/** Query which DTMIDs this DTM is currently using within the DTMManager. |
|
2352 |
* |
|
2353 |
* %REVEW% Should this become part of the base DTM API? |
|
2354 |
* |
|
2355 |
* @return an IntVector, or null if this is a "stand-alone" DTM. |
|
2356 |
*/ |
|
2357 |
public SuballocatedIntVector getDTMIDs() |
|
2358 |
{ |
|
2359 |
if(m_mgr==null) return null; |
|
2360 |
return m_dtmIdent; |
|
2361 |
} |
|
2362 |
} |