View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.log4j.chainsaw;
19  
20  import java.util.AbstractList;
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.List;
24  
25  
26  /**
27   * CyclicBuffer implementation that is Object generic, and implements the List interface.
28   * <p>
29   * Original CyclicBuffer @author Ceki G&uuml;lc&uuml;
30   * <p>
31   * This implementation (although there's very little change) @author Paul Smith &lt;psmith@apache.org&gt;
32   */
33  public class CyclicBufferList extends AbstractList implements List {
34      Object[] ea;
35      int first;
36      int last;
37      int numElems;
38      int maxSize;
39  
40      /**
41       * Instantiate a new CyclicBuffer of at most <code>maxSize</code> events.
42       * <p>
43       * The <code>maxSize</code> argument must a positive integer.
44       *
45       * @param maxSize The maximum number of elements in the buffer.
46       */
47      public CyclicBufferList(int maxSize) {
48          if (maxSize < 1) {
49              throw new IllegalArgumentException(
50                  "The maxSize argument (" + maxSize + ") is not a positive integer.");
51          }
52          this.maxSize = maxSize;
53          clear();
54      }
55  
56      public CyclicBufferList() {
57          this(5000);
58      }
59  
60      /**
61       * Removes the element at the specified position in this list.
62       * Shifts any subsequent elements to the left (subtracts one from their
63       * indices).
64       *
65       * @param index the index of the element to removed.
66       * @return the element that was removed from the list.
67       * @throws IndexOutOfBoundsException if index out of range <tt>(index
68       *                                   &lt; 0 || index &gt;= size())</tt>.
69       */
70      public Object remove(int index) {
71          Object oldValue = ea[index];
72  
73          List list = new ArrayList(Arrays.asList(ea));
74          list.remove(index);
75          ea = list.toArray(ea);
76          numElems = ea.length;
77  
78          numElems--;
79          if (--last <= 0) {
80              last = numElems;
81          }
82  
83          if (first == maxSize) {
84              first = 0;
85          }
86          return oldValue;
87      }
88  
89      public Object set(int index, Object element) {
90          Object previous = ea[index];
91          ea[index] = element;
92  
93          return previous;
94      }
95  
96      /**
97       * Add an <code>event</code> as the last event in the buffer.
98       */
99      public boolean add(Object event) {
100         ea[last] = event;
101 
102         if (++last == maxSize) {
103             last = 0;
104         }
105 
106         if (numElems < maxSize) {
107             numElems++;
108         } else if (++first == maxSize) {
109             first = 0;
110         }
111 
112         return true;
113     }
114 
115     /**
116      * Get the <i>i</i>th oldest event currently in the buffer. If
117      * <em>i</em> is outside the range 0 to the number of elements
118      * currently in the buffer, then <code>null</code> is returned.
119      */
120     public Object get(int i) {
121         if ((i < 0) || (i >= numElems)) {
122             return null;
123         }
124 
125         return ea[(first + i) % maxSize];
126     }
127 
128     public int getMaxSize() {
129         return maxSize;
130     }
131 
132     public int getLast() {
133         return last;
134     }
135 
136     /**
137      * Get the oldest (first) element in the buffer. The oldest element
138      * is removed from the buffer.
139      */
140     public Object get() {
141         Object r = null;
142 
143         if (numElems > 0) {
144             numElems--;
145             r = ea[first];
146             ea[first] = null;
147 
148             if (++first == maxSize) {
149                 first = 0;
150             }
151         }
152 
153         return r;
154     }
155 
156     /**
157      * Get the number of elements in the buffer. This number is
158      * guaranteed to be in the range 0 to <code>maxSize</code>
159      * (inclusive).
160      */
161     public int size() {
162         return numElems;
163     }
164 
165     /**
166      * Resize the cyclic buffer to <code>newSize</code>.
167      *
168      * @throws IllegalArgumentException if <code>newSize</code> is negative.
169      */
170     public void resize(int newSize) {
171         if (newSize < 0) {
172             throw new IllegalArgumentException(
173                 "Negative array size [" + newSize + "] not allowed.");
174         }
175 
176         if (newSize == numElems) {
177             return; // nothing to do
178         }
179 
180         Object[] temp = new Object[newSize];
181 
182         int loopLen = (newSize < numElems) ? newSize : numElems;
183 
184         for (int i = 0; i < loopLen; i++) {
185             temp[i] = ea[first];
186             ea[first] = null;
187 
188             if (++first == numElems) {
189                 first = 0;
190             }
191         }
192 
193         ea = temp;
194         first = 0;
195         numElems = loopLen;
196         maxSize = newSize;
197 
198         if (loopLen == newSize) {
199             last = 0;
200         } else {
201             last = loopLen;
202         }
203     }
204 
205     /* (non-Javadoc)
206      * @see java.util.Collection#clear()
207      */
208     public void clear() {
209         ea = new Object[maxSize];
210         first = 0;
211         last = 0;
212         numElems = 0;
213 
214     }
215 
216 }