View Javadoc

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 }