1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.mina.util.byteaccess;
21
22
23 import java.util.NoSuchElementException;
24
25
26 /**
27 * A linked list that stores <code>ByteArray</code>s and maintains several useful invariants.
28 *
29 * @author The Apache MINA Project (dev@mina.apache.org)
30 * @version $Rev$, $Date$
31 */
32 class ByteArrayList
33 {
34
35 /**
36 * A {@link Node} which indicates the start and end of the list and does not
37 * hold a value. The value of <code>next</code> is the first item in the
38 * list. The value of of <code>previous</code> is the last item in the list.
39 */
40 private final Node header;
41
42 /**
43 * The first byte in the array list
44 */
45 private int firstByte;
46
47 /**
48 * The last byte in the array list
49 */
50 private int lastByte;
51
52 /**
53 *
54 * Creates a new instance of ByteArrayList.
55 *
56 */
57 protected ByteArrayList()
58 {
59 header = new Node();
60 }
61
62 /**
63 *
64 * Returns the last byte in the array list
65 *
66 * @return
67 * The last byte in the array list
68 */
69 public int lastByte()
70 {
71 return lastByte;
72 }
73
74 /**
75 *
76 * Returns the first byte in the array list
77 *
78 * @return
79 * The first byte in the array list
80 */
81 public int firstByte()
82 {
83 return firstByte;
84 }
85
86 /**
87 *
88 * Check to see if this is empty
89 *
90 * @return
91 * True if empty, otherwise false
92 */
93 public boolean isEmpty()
94 {
95 return header.next == header;
96 }
97
98 /**
99 * Returns the first node in the byte array
100 *
101 * @return
102 *
103 */
104 public Node getFirst()
105 {
106 return header.getNextNode();
107 }
108
109 /**
110 * Returns the last {@link Node} in the list
111 *
112 * @return
113 * The last node in the list
114 */
115 public Node getLast()
116 {
117 return header.getPreviousNode();
118 }
119
120 /**
121 * Adds the specified {@link ByteArray} to
122 * the beginning of the list
123 *
124 * @param ba
125 * The ByteArray to be added to the list
126 */
127 public void addFirst( ByteArray ba )
128 {
129 addNode( new Node( ba ), header.next );
130 firstByte -= ba.last();
131 }
132
133 /**
134 * Add the specified {@link ByteArray} to
135 * the end of the list
136 *
137 * @param ba
138 * The ByteArray to be added to the list
139 */
140 public void addLast( ByteArray ba )
141 {
142 addNode( new Node( ba ), header );
143 lastByte += ba.last();
144 }
145
146 /**
147 * Removes the first node from this list
148 *
149 * @return
150 * The node that was removed
151 */
152 public Node removeFirst()
153 {
154 Node node = header.getNextNode();
155 firstByte += node.ba.last();
156 return removeNode( node );
157 }
158
159 /**
160 * Removes the last node in this list
161 *
162 * @return
163 * The node that was taken off of the list
164 */
165 public Node removeLast()
166 {
167 Node node = header.getPreviousNode();
168 lastByte -= node.ba.last();
169 return removeNode( node );
170 }
171
172
173 //-----------------------------------------------------------------------
174
175 /**
176 * Inserts a new node into the list.
177 *
178 * @param nodeToInsert new node to insert
179 * @param insertBeforeNode node to insert before
180 * @throws NullPointerException if either node is null
181 */
182 protected void addNode( Node nodeToInsert, Node insertBeforeNode )
183 {
184 // Insert node.
185 nodeToInsert.next = insertBeforeNode;
186 nodeToInsert.previous = insertBeforeNode.previous;
187 insertBeforeNode.previous.next = nodeToInsert;
188 insertBeforeNode.previous = nodeToInsert;
189 }
190
191
192 /**
193 * Removes the specified node from the list.
194 *
195 * @param node the node to remove
196 * @throws NullPointerException if <code>node</code> is null
197 */
198 protected Node removeNode( Node node )
199 {
200 // Remove node.
201 node.previous.next = node.next;
202 node.next.previous = node.previous;
203 node.removed = true;
204 return node;
205 }
206
207 //-----------------------------------------------------------------------
208 /**
209 * A node within the linked list.
210 * <p>
211 * From Commons Collections 3.1, all access to the <code>value</code> property
212 * is via the methods on this class.
213 */
214 public class Node
215 {
216
217 /** A pointer to the node before this node */
218 private Node previous;
219
220 /** A pointer to the node after this node */
221 private Node next;
222
223 /** The ByteArray contained within this node */
224 private ByteArray ba;
225
226 private boolean removed;
227
228
229 /**
230 * Constructs a new header node.
231 */
232 private Node()
233 {
234 super();
235 previous = this;
236 next = this;
237 }
238
239
240 /**
241 * Constructs a new node with a value.
242 */
243 private Node( ByteArray ba )
244 {
245 super();
246
247 if ( ba == null )
248 {
249 throw new NullPointerException( "ByteArray must not be null." );
250 }
251 this.ba = ba;
252 }
253
254
255 /**
256 * Gets the previous node.
257 *
258 * @return the previous node
259 */
260 public Node getPreviousNode()
261 {
262 if ( !hasPreviousNode() )
263 {
264 throw new NoSuchElementException();
265 }
266 return previous;
267 }
268
269
270 /**
271 * Gets the next node.
272 *
273 * @return the next node
274 */
275 public Node getNextNode()
276 {
277 if ( !hasNextNode() )
278 {
279 throw new NoSuchElementException();
280 }
281 return next;
282 }
283
284
285 public boolean hasPreviousNode()
286 {
287 return previous != header;
288 }
289
290
291 public boolean hasNextNode()
292 {
293 return next != header;
294 }
295
296
297 public ByteArray getByteArray()
298 {
299 return ba;
300 }
301
302
303 public boolean isRemoved()
304 {
305 return removed;
306 }
307 }
308
309 }