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