001package votorola.a.voter; // Copyright 2008, Michael Allan.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE.
002
003import java.io.*;
004import java.util.*;
005import votorola.g.lang.*;
006import votorola.g.util.*;
007
008
009/** A rolling list of activity events, beginning with the most recent.  New events that
010  * are added to the list will roll over (overwrite) old ones, so the size of the list
011  * will never exceed its fixed capacity.
012  */
013public class ActivityList extends AbstractList<ActivityEvent> implements java.io.Serializable
014{
015
016    private static final long serialVersionUID = 1L;
017
018
019
020    /** Inserts a new event at the beginning of this list.  If the list was already
021      * at capacity size, then the oldest event is removed from the end.
022      *
023      *     @param e event to be inserted; or null, to insert no event
024      */
025    public void log( ActivityEvent e )
026    {
027        if( e == null ) return;
028
029        int actualIndexOfLogicalZero = offsetter.actualIndex( -1 ); // rolling backwards
030        offsetter.setActualIndexOfLogicalZero( actualIndexOfLogicalZero );
031        eventArray[actualIndexOfLogicalZero] = e;
032        if( size < eventArray.length ) ++size;
033    }
034
035
036
037   // - C o l l e c t i o n --------------------------------------------------------------
038
039
040    public final @Override int size() { return size; }
041
042
043        private int size;
044
045
046
047   // - L i s t --------------------------------------------------------------------------
048
049
050    public final @Override ActivityEvent get( int index )
051    {
052        return eventArray[offsetter.actualIndex(index)];
053    }
054
055
056
057   // ====================================================================================
058
059
060    /** An activity list that allows for thread-safe logging.
061      * Its log(e) method synchronizes on monitor lock TL.this.
062      */
063    public static final class TL extends ActivityList
064    {
065
066        public @ThreadSafe synchronized @Override void log( ActivityEvent e ) { super.log( e ); }
067
068    }
069
070
071
072//// P r i v a t e ///////////////////////////////////////////////////////////////////////
073
074
075    /** The maximum size (number of events) for a newly constructed activity list.
076      */
077    private static final int CAPACITY = 100; // Changing? Increment serialVersionUID to prevent deserialization of old lists, having the old size
078
079
080
081    private final ActivityEvent[] eventArray = new ActivityEvent[CAPACITY];
082
083
084
085    private final IndexOffsetter offsetter = new IndexOffsetter( CAPACITY );
086
087
088
089}