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 }