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 <a href="http://mina.apache.org">Apache MINA Project</a>
30   */
31  class ByteArrayList
32  {
33  
34      /**
35       * A {@link Node} which indicates the start and end of the list and does not
36       * hold a value. The value of <code>next</code> is the first item in the
37       * list. The value of of <code>previous</code> is the last item in the list.
38       */
39      private final Node header;
40  
41      /**
42       * The first byte in the array list
43       */
44      private int firstByte;
45  
46      /**
47       * The last byte in the array list
48       */
49      private int lastByte;
50  
51      /**
52       * 
53       * Creates a new instance of ByteArrayList.
54       *
55       */
56      protected ByteArrayList()
57      {
58          header = new Node();
59      }
60  
61      /**
62       * 
63       * Returns the last byte in the array list
64       *
65       * @return
66       *  The last byte in the array list
67       */
68      public int lastByte()
69      {
70          return lastByte;
71      }
72  
73      /**
74       * 
75       * Returns the first byte in the array list
76       *
77       * @return
78       *  The first byte in the array list
79       */
80      public int firstByte()
81      {
82          return firstByte;
83      }
84  
85      /**
86       * 
87       * Check to see if this is empty
88       *
89       * @return
90       *  True if empty, otherwise false
91       */
92      public boolean isEmpty()
93      {
94          return header.next == header;
95      }
96  
97      /**
98       * Returns the first node in the byte array
99       *
100      * @return
101      *  
102      */
103     public Node getFirst()
104     {
105         return header.getNextNode();
106     }
107 
108     /**
109      * Returns the last {@link Node} in the list
110      *
111      * @return
112      *  The last node in the list
113      */
114     public Node getLast()
115     {
116         return header.getPreviousNode();
117     }
118 
119     /**
120      * Adds the specified {@link ByteArray} to 
121      * the beginning of the list
122      *
123      * @param ba
124      *  The ByteArray to be added to the list
125      */
126     public void addFirst( ByteArray ba )
127     {
128         addNode( new Node( ba ), header.next );
129         firstByte -= ba.last();
130     }
131 
132     /**
133      * Add the specified {@link ByteArray} to 
134      * the end of the list 
135      *
136      * @param ba
137      *  The ByteArray to be added to the list
138      */
139     public void addLast( ByteArray ba )
140     {
141         addNode( new Node( ba ), header );
142         lastByte += ba.last();
143     }
144 
145     /**
146      * Removes the first node from this list
147      *
148      * @return
149      *  The node that was removed
150      */
151     public Node removeFirst()
152     {
153         Node node = header.getNextNode();
154         firstByte += node.ba.last();
155         return removeNode( node );
156     }
157 
158     /**
159      * Removes the last node in this list
160      *
161      * @return
162      *  The node that was taken off of the list
163      */
164     public Node removeLast()
165     {
166         Node node = header.getPreviousNode();
167         lastByte -= node.ba.last();
168         return removeNode( node );
169     }
170 
171 
172     //-----------------------------------------------------------------------
173 
174     /**
175      * Inserts a new node into the list.
176      *
177      * @param nodeToInsert  new node to insert
178      * @param insertBeforeNode  node to insert before
179      * @throws NullPointerException if either node is null
180      */
181     protected void addNode( Node nodeToInsert, Node insertBeforeNode )
182     {
183         // Insert node.
184         nodeToInsert.next = insertBeforeNode;
185         nodeToInsert.previous = insertBeforeNode.previous;
186         insertBeforeNode.previous.next = nodeToInsert;
187         insertBeforeNode.previous = nodeToInsert;
188     }
189 
190 
191     /**
192      * Removes the specified node from the list.
193      *
194      * @param node  the node to remove
195      * @throws NullPointerException if <code>node</code> is null
196      */
197     protected Node removeNode( Node node )
198     {
199         // Remove node.
200         node.previous.next = node.next;
201         node.next.previous = node.previous;
202         node.removed = true;
203         return node;
204     }
205 
206     //-----------------------------------------------------------------------
207     /**
208      * A node within the linked list.
209      * <p>
210      * From Commons Collections 3.1, all access to the <code>value</code> property
211      * is via the methods on this class.
212      */
213     public class Node
214     {
215 
216         /** A pointer to the node before this node */
217         private Node previous;
218         
219         /** A pointer to the node after this node */
220         private Node next;
221         
222         /** The ByteArray contained within this node */
223         private ByteArray ba;
224         
225         private boolean removed;
226 
227 
228         /**
229          * Constructs a new header node.
230          */
231         private Node()
232         {
233             super();
234             previous = this;
235             next = this;
236         }
237 
238 
239         /**
240          * Constructs a new node with a value.
241          */
242         private Node( ByteArray ba )
243         {
244             super();
245             
246             if ( ba == null )
247             {
248                 throw new NullPointerException( "ByteArray must not be null." );
249             }
250             this.ba = ba;
251         }
252 
253 
254         /**
255          * Gets the previous node.
256          *
257          * @return the previous node
258          */
259         public Node getPreviousNode()
260         {
261             if ( !hasPreviousNode() )
262             {
263                 throw new NoSuchElementException();
264             }
265             return previous;
266         }
267 
268 
269         /**
270          * Gets the next node.
271          *
272          * @return the next node
273          */
274         public Node getNextNode()
275         {
276             if ( !hasNextNode() )
277             {
278                 throw new NoSuchElementException();
279             }
280             return next;
281         }
282 
283 
284         public boolean hasPreviousNode()
285         {
286             return previous != header;
287         }
288 
289 
290         public boolean hasNextNode()
291         {
292             return next != header;
293         }
294 
295 
296         public ByteArray getByteArray()
297         {
298             return ba;
299         }
300 
301 
302         public boolean isRemoved()
303         {
304             return removed;
305         }
306     }
307 
308 }