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   *
    28   * CyclicBuffer implementation that is Object generic, and implements the List interface.
    29   *
    30   * Original CyclicBuffer @author Ceki G&uuml;lc&uuml;
    31   *
    32   * This implementation (although there's very little change) @author Paul Smith &lt;psmith@apache.org&gt;
    33   *
    34   */
    35  public class CyclicBufferList extends AbstractList implements List {
    36    Object[] ea;
    37    int first;
    38    int last;
    39    int numElems;
    40    int maxSize;
    41
    42    /**
    43       Instantiate a new CyclicBuffer of at most <code>maxSize</code> events.
    44
    45       The <code>maxSize</code> argument must a positive integer.
    46
    47       @param maxSize The maximum number of elements in the buffer.
    48    */
    49    public CyclicBufferList(int maxSize) {
    50      if (maxSize < 1) {
    51        throw new IllegalArgumentException(
    52          "The maxSize argument (" + maxSize + ") is not a positive integer.");
    53      }
    54      this.maxSize = maxSize;
    55      clear();
    56    }
    57
    58    public CyclicBufferList() {
    59      this(5000);
    60    }
    61
    62    /**
    63     * Removes the element at the specified position in this list.
    64     * Shifts any subsequent elements to the left (subtracts one from their
    65     * indices).
    66     *
    67     * @param index the index of the element to removed.
    68     * @return the element that was removed from the list.
    69     * @throws    IndexOutOfBoundsException if index out of range <tt>(index
    70     *      &lt; 0 || index &gt;= size())</tt>.
    71     */
    72    public Object remove(int index) {
    73      Object oldValue = ea[index];
    74
    75      List list = new ArrayList(Arrays.asList(ea));
    76      list.remove(index);
    77      ea = list.toArray(ea);
    78      numElems = ea.length;
    79
    80      numElems--;
    81      if (--last <= 0) {
    82        last = numElems;
    83      }
    84
    85      if (first == maxSize) {
    86        first = 0;
    87      }
    88      return oldValue;
    89    }
    90
    91    public Object set(int index, Object element) {
    92      Object previous = ea[index];
    93      ea[index] = element;
    94
    95      return previous;
    96    }
    97
    98    /**
    99       Add an <code>event</code> as the last event in the buffer.
    100
    101    */
    102   public boolean add(Object event) {
    103     ea[last] = event;
    104
    105     if (++last == maxSize) {
    106       last = 0;
    107     }
    108
    109     if (numElems < maxSize) {
    110       numElems++;
    111     } else if (++first == maxSize) {
    112       first = 0;
    113     }
    114
    115     return true;
    116   }
    117
    118   /**
    119      Get the <i>i</i>th oldest event currently in the buffer. If
    120      <em>i</em> is outside the range 0 to the number of elements
    121      currently in the buffer, then <code>null</code> is returned.
    122
    123
    124   */
    125   public Object get(int i) {
    126     if ((i < 0) || (i >= numElems)) {
    127       return null;
    128     }
    129
    130     return ea[(first + i) % maxSize];
    131   }
    132
    133   public int getMaxSize() {
    134     return maxSize;
    135   }
    136
    137   public int getLast() {
    138       return last;
    139   }
    140
    141   /**
    142      Get the oldest (first) element in the buffer. The oldest element
    143      is removed from the buffer.
    144   */
    145   public Object get() {
    146     Object r = null;
    147
    148     if (numElems > 0) {
    149       numElems--;
    150       r = ea[first];
    151       ea[first] = null;
    152
    153       if (++first == maxSize) {
    154         first = 0;
    155       }
    156     }
    157
    158     return r;
    159   }
    160
    161   /**
    162      Get the number of elements in the buffer. This number is
    163      guaranteed to be in the range 0 to <code>maxSize</code>
    164      (inclusive).
    165   */
    166   public int size() {
    167     return numElems;
    168   }
    169
    170   /**
    171      Resize the cyclic buffer to <code>newSize</code>.
    172
    173      @throws IllegalArgumentException if <code>newSize</code> is negative.
    174    */
    175   public void resize(int newSize) {
    176     if (newSize < 0) {
    177       throw new IllegalArgumentException(
    178         "Negative array size [" + newSize + "] not allowed.");
    179     }
    180
    181     if (newSize == numElems) {
    182       return; // nothing to do
    183     }
    184
    185     Object[] temp = new Object[newSize];
    186
    187     int loopLen = (newSize < numElems) ? newSize : numElems;
    188
    189     for (int i = 0; i < loopLen; i++) {
    190       temp[i] = ea[first];
    191       ea[first] = null;
    192
    193       if (++first == numElems) {
    194         first = 0;
    195       }
    196     }
    197
    198     ea = temp;
    199     first = 0;
    200     numElems = loopLen;
    201     maxSize = newSize;
    202
    203     if (loopLen == newSize) {
    204       last = 0;
    205     } else {
    206       last = loopLen;
    207     }
    208   }
    209   /* (non-Javadoc)
    210    * @see java.util.Collection#clear()
    211    */
    212   public void clear() {
    213     ea = new Object[maxSize];
    214     first = 0;
    215     last = 0;
    216     numElems = 0;
    217
    218   }
    219
    220 }