View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript-Util: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2005 Kevin Rogers
4   //
5   // This file is part of MillScript-Util.
6   //
7   // MillScript-Util is free software; you can redistribute it and/or modify it under
8   // the terms of the GNU General Public License as published by the Free
9   // Software Foundation; either version 2 of the License, or (at your option)
10  // any later version.
11  //
12  // MillScript-Util is distributed in the hope that it will be useful, but WITHOUT
13  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  // more details.
16  //
17  // You should have received a copy of the GNU General Public License along with
18  // MillScript-Util; if not, write to the Free Software Foundation, Inc., 59 Temple
19  // Place, Suite 330, Boston, MA  02111-1307  USA
20  ////////////////////////////////////////////////////////////////////////////////
21  package org.millscript.commons.util.list;
22  
23  import java.io.Serializable;
24  
25  import org.millscript.commons.util.IList;
26  import org.millscript.commons.util.ListIterator;
27  import org.millscript.commons.util.alerts.ListIndexOutOfBoundsAlert;
28  import org.millscript.commons.util.iterator.ArrayListIterator;
29  import org.millscript.commons.util.iterator.NullListIterator;
30  import org.millscript.commons.util.iterator.SharedArrayListIterator;
31  
32  /**
33   * This class provides an immutable <code>List</code> implementation which is
34   * backed by a slice of an Object array. This class allows you to conveniently
35   * share store between different lists.
36   */
37  public class ISharedArrayList< V > extends AbstractIList< V > implements Cloneable, Serializable {
38  
39      /**
40       * This is the ID from the release 0.1.0 for future compatibility.
41       */
42      private static final long serialVersionUID = 6049801407468696384L;
43  
44      /**
45       * The index of the first element of this list in the backing store.
46       */
47      private final int firstIndex;
48  
49      /**
50       * The index of the last element of this list in the backing store.
51       */
52      private final int lastIndex;
53      
54      /**
55       * The backing store containing a fixed array of objects.
56       */
57      private final V[] store;
58  
59      /**
60       * Constructs a new immutable array list with a slice of the specified
61       * backing object array.
62       *
63       * @param objects   the backing object array(only kept if start &lt;= end )
64       * @param start the index(one based, inclusive) of the first element in the
65       * slice
66       * @param end   the index(one based, inclusive) of the last element in the
67       * slice. If end &lt; start, the new list will be empty
68       */
69      public ISharedArrayList( final V[] objects, final int start, final int end ) {
70          if ( start > end ) {
71              this.store = null;
72          } else if ( start < 1 || start > objects.length ) {
73              throw new ListIndexOutOfBoundsAlert(
74                  "First index in slice must be between 1 and the length of the array"
75              ).culprit(
76                  "index",
77                  start
78              ).decorate( objects ).mishap();
79          } else if ( end > objects.length ) {
80              throw new ListIndexOutOfBoundsAlert(
81                  "Last index in slice must not be greater than the length of the array"
82              ).culprit(
83                  "index",
84                  end
85              ).decorate( objects ).mishap();
86          } else {
87              this.store = objects;
88          }
89          this.firstIndex = start;
90          this.lastIndex = end;
91      }
92  
93      /**
94       * @see java.lang.Object#clone()
95       */
96      @Override
97      public Object clone() throws CloneNotSupportedException {
98          // Nothing special required for this clone
99          return super.clone();
100     }
101 
102     /**
103      * @see org.millscript.commons.util.list.AbstractIList#doGet(int)
104      */
105     @Override
106     protected V doGet( final int pos ) {
107         // NOTE - We subtract two here as both firstElementIndex and pos use
108         // one based indexing, so we have to subtract one from both
109         return this.store[ this.firstIndex - 2 + pos ];
110     }
111 
112     /**
113      * @see org.millscript.commons.util.list.AbstractIList#doSlice(int, int, boolean)
114      */
115     @Override
116     protected IList< V > doSlice( final int first, final int last, final boolean share ) {
117         // The off by one adjustment is required as the indicies are inclusive,
118         // so if first is one we must use the value of firstIndex.
119         if ( share ) {
120             return new ISharedArrayList< V >(
121                 this.store,
122                 this.firstIndex + first - 1,
123                 this.firstIndex + last - 1
124             );
125         } else {
126             return new IArrayList< V >(
127                 this.store,
128                 this.firstIndex + first - 1,
129                 this.firstIndex + last - 1
130             );
131         }
132     }
133 
134     /**
135      * @see org.millscript.commons.util.IList#indexOf(java.lang.Object)
136      */
137     public int indexOf( final V value ) {
138         for ( int i = this.firstIndex - 1; i < this.lastIndex; i++ ) {
139             if ( value == null ? this.store[ i ] == null : value.equals( this.store[ i ] ) ) {
140                 return i - this.firstIndex + 2;
141             }
142         }
143         return 0;
144     }
145 
146     /**
147      * @see org.millscript.commons.util.IMap#iterator(boolean)
148      */
149     @SuppressWarnings( "unchecked" )
150     public ListIterator< V > iterator( final boolean share ) {
151         if ( share ) {
152             return new SharedArrayListIterator< V >(
153                 this.store,
154                 this.firstIndex,
155                 this.lastIndex
156             );
157         } else if ( this.size() == 0 ) {
158             return new NullListIterator< V >();
159         } else {
160             final V[] objects = (V[]) new Object[ this.size() ];
161             System.arraycopy( this.store, this.firstIndex - 1, objects, 0, objects.length );
162             return new ArrayListIterator< V >( objects, true );
163         }
164     }
165 
166     /**
167      * @see org.millscript.commons.util.IMap#size()
168      */
169     public int size() {
170         return this.lastIndex < this.firstIndex ? 0
171                                                 : this.lastIndex - this.firstIndex + 1;
172     }
173 
174 }