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      */
180     protected void addNode( Node nodeToInsert, Node insertBeforeNode )
181     {
182         // Insert node.
183         nodeToInsert.next = insertBeforeNode;
184         nodeToInsert.previous = insertBeforeNode.previous;
185         insertBeforeNode.previous.next = nodeToInsert;
186         insertBeforeNode.previous = nodeToInsert;
187     }
188 
189 
190     /**
191      * Removes the specified node from the list.
192      *
193      * @param node  the node to remove
194      */
195     protected Node removeNode( Node node )
196     {
197         // Remove node.
198         node.previous.next = node.next;
199         node.next.previous = node.previous;
200         node.removed = true;
201         return node;
202     }
203 
204     //-----------------------------------------------------------------------
205     /**
206      * A node within the linked list.
207      * <p>
208      * From Commons Collections 3.1, all access to the <code>value</code> property
209      * is via the methods on this class.
210      */
211     public class Node
212     {
213 
214         /** A pointer to the node before this node */
215         private Node previous;
216         
217         /** A pointer to the node after this node */
218         private Node next;
219         
220         /** The ByteArray contained within this node */
221         private ByteArray ba;
222         
223         private boolean removed;
224 
225 
226         /**
227          * Constructs a new header node.
228          */
229         private Node()
230         {
231             super();
232             previous = this;
233             next = this;
234         }
235 
236 
237         /**
238          * Constructs a new node with a value.
239          */
240         private Node( ByteArray ba )
241         {
242             super();
243             
244             if ( ba == null )
245             {
246                 throw new IllegalArgumentException( "ByteArray must not be null." );
247             }
248             
249             this.ba = ba;
250         }
251 
252 
253         /**
254          * Gets the previous node.
255          *
256          * @return the previous node
257          */
258         public Node getPreviousNode()
259         {
260             if ( !hasPreviousNode() )
261             {
262                 throw new NoSuchElementException();
263             }
264             return previous;
265         }
266 
267 
268         /**
269          * Gets the next node.
270          *
271          * @return the next node
272          */
273         public Node getNextNode()
274         {
275             if ( !hasNextNode() )
276             {
277                 throw new NoSuchElementException();
278             }
279             return next;
280         }
281 
282 
283         public boolean hasPreviousNode()
284         {
285             return previous != header;
286         }
287 
288 
289         public boolean hasNextNode()
290         {
291             return next != header;
292         }
293 
294 
295         public ByteArray getByteArray()
296         {
297             return ba;
298         }
299 
300 
301         public boolean isRemoved()
302         {
303             return removed;
304         }
305     }
306 
307 }