1 /*
2 * Copyright (C) 2002 Carsten Krebs (Team-Konzept GmbH & Co.KG)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 package com.teamkonzept.dom4jb.dom;
19
20 public class FilteredNodeList implements org.w3c.dom.NodeList {
21
22 protected final int initialCapacity = 8;
23 /***
24 * The array buffer into which the elements of the NodeList are stored.
25 * The capacity of the ArrayList is the length of this array buffer.
26 */
27 private Node nodeData[];
28 private NodeList baseList;
29 private int baseIndex;
30 private Filter filter;
31
32 /***
33 * The size of the NodeList (the number of elements it contains).
34 *
35 * @serial
36 */
37 private int size;
38
39 public FilteredNodeList( final NodeList baseList, final Filter filter ) {
40 this.baseList = baseList;
41 this.filter = filter;
42 this.baseIndex = 0;
43 this.nodeData = new Node[initialCapacity];
44 this.size = 0;
45 }
46
47
48 /***
49 * Trims the capacity of this <tt>NodeList</tt> instance to be the
50 * list's current size. An application can use this operation to minimize
51 * the storage of an <tt>NodeList</tt> instance.
52 */
53 public void trimToSize() {
54 final int oldCapacity = nodeData.length;
55 if (size < oldCapacity) {
56 final Node oldData[] = nodeData;
57 nodeData = new Node[size];
58 System.arraycopy(oldData, 0, nodeData, 0, size);
59 }
60 }
61
62 /***
63 * Increases the capacity of this <tt>NodeList</tt> instance, if
64 * necessary, to ensure that it can hold at least the number of elements
65 * specified by the minimum capacity argument.
66 *
67 * @param minCapacity the desired minimum capacity.
68 */
69 public void ensureCapacity(final int minCapacity) {
70 final int oldCapacity = nodeData.length;
71 if (minCapacity > oldCapacity) {
72 final Node oldData[] = nodeData;
73 int newCapacity = (oldCapacity * 3)/2 + 1;
74 if (newCapacity < minCapacity)
75 newCapacity = minCapacity;
76 nodeData = new Node[newCapacity];
77 System.arraycopy(oldData, 0, nodeData, 0, size);
78 }
79 }
80
81 /***
82 * Returns the number of elements in this list.
83 *
84 * @return the number of elements in this list.
85 */
86 public int size() {
87 if ( baseList == null ) {
88 return size;
89 }
90 Node nextNode;
91 do {
92 nextNode = baseList.get( baseIndex++ );
93 if ( filter.match(nextNode) ) {
94 add( nextNode );
95 }
96 } while ( nextNode != null );
97 baseList = null;
98 return size;
99 }
100
101 /***
102 * The number of nodes in the list. The range of valid child node indices
103 * is 0 to <code>length-1</code> inclusive.
104 */
105 public int getLength() {
106 return size();
107 }
108
109 /***
110 * Tests if this list has no elements.
111 *
112 * @return <tt>true</tt> if this list has no elements;
113 * <tt>false</tt> otherwise.
114 */
115 public boolean isEmpty() {
116 if ( size > 0 ) {
117 return false;
118 }
119 if ( baseList == null ) {
120 return true;
121 }
122 Node nextNode;
123 do {
124 nextNode = baseList.get( baseIndex++ );
125 if ( filter.match(nextNode) ) {
126 add( nextNode );
127 return false;
128 }
129 } while ( nextNode != null );
130 baseList = null;
131 return true;
132 }
133
134 // Positional Access Operations
135
136 /***
137 * Returns the <code>index</code>th item in the collection. If
138 * <code>index</code> is greater than or equal to the number of nodes in
139 * the list, this returns <code>null</code>.
140 * @param index Index into the collection.
141 * @return The node at the <code>index</code>th position in the
142 * <code>NodeList</code>, or <code>null</code> if that is not a valid
143 * index.
144 */
145 public Node get(final int index) {
146 if ( index < 0 ) {
147 return null;
148 }
149 if ( index < size ) {
150 return nodeData[index];
151 }
152 if ( baseList != null ) {
153 Node nextNode;
154 do {
155 nextNode = (Node)baseList.item( baseIndex++ );
156 if ( filter.match(nextNode) ) {
157 add( nextNode );
158 }
159 } while ( index >= size && nextNode != null );
160 if ( index < size ) {
161 return nodeData[index];
162 }
163 baseList = null;
164 }
165 return null;
166 }
167
168 /***
169 * Returns the <code>index</code>th item in the collection. If
170 * <code>index</code> is greater than or equal to the number of nodes in
171 * the list, this returns <code>null</code>.
172 * @param index Index into the collection.
173 * @return The node at the <code>index</code>th position in the
174 * <code>NodeList</code>, or <code>null</code> if that is not a valid
175 * index.
176 */
177 public org.w3c.dom.Node item(final int index ) {
178 return get( index );
179 }
180
181 /***
182 * Appends the specified element to the end of this list.
183 *
184 * @param o element to be appended to this list.
185 * @return <tt>true</tt> (as per the general contract of Collection.add).
186 */
187 private boolean add( final Node o ) {
188 ensureCapacity(size + 1);
189 nodeData[size] = o;
190 return true;
191 }
192
193 /***
194 * Removes all of the elements from this list. The list will
195 * be empty after this call returns.
196 */
197 public void clear() {
198
199 // Let gc do its work
200 for (int i = 0; i < size; i++) {
201 nodeData[i] = null;
202 }
203
204 baseList = null;
205
206 baseIndex = 0;
207 size = 0;
208 }
209 }
This page was automatically generated by Maven