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  import java.lang.reflect.Array;
25  
26  import org.millscript.commons.alert.alerts.Fault;
27  import org.millscript.commons.util.IList;
28  import org.millscript.commons.util.ListIterator;
29  import org.millscript.commons.util.alerts.ListIndexOutOfBoundsAlert;
30  import org.millscript.commons.util.iterator.ArrayListIterator;
31  
32  /**
33   * This class provides an immutable <code>List</code> implementation which is
34   * backed by an Object array.
35   */
36  public class IArrayList< V > extends AbstractIList< V > implements Cloneable, Serializable {
37  
38      /**
39       * This is the ID from the release 0.1.0 for future compatibility.
40       */
41      private static final long serialVersionUID = 1608901978039433493L;
42      /**
43       * The backing store containing a fixed array of objects.
44       */
45      private final V[] store;
46  
47      /**
48       * Constructs a new empty immutable array list. 
49       */
50      public IArrayList() {
51          this.store = null;
52      }
53  
54      /**
55       * Constructs a new immutable array list with the specified backing object
56       * array.
57       *
58       * @param objects   the backing object array to copy
59       * @param share if <code>true</code> the specified object array will be
60       * shared otherwise the array will be copied.
61       */
62      @SuppressWarnings( "unchecked" )
63      public IArrayList( final V[] objects, final boolean share ) {
64          if ( objects == null || share ) {
65              this.store = objects;
66          } else {
67              this.store = (V[]) new Object[ objects.length ];
68              System.arraycopy( objects, 0, this.store, 0, objects.length );
69          }
70      }
71  
72      /**
73       * Constructs a new immutable array list with a copy of the specified
74       * backing object array, starting and ending at the specified indices.
75       *
76       * @param objects   the backing object array to copy
77       * @param start the index(one based, inclusive) of the first element in the
78       * slice
79       * @param end   the index(one based, inclusive) of the last element in the
80       * slice. If end &lt; start, the new list will be empty
81       */
82      @SuppressWarnings( "unchecked" )
83      public IArrayList( final V[] objects, final int start, final int end ) {
84          if ( start > end ) {
85              this.store = null;
86          } else if ( start < 1 || start > objects.length ) {
87              throw new ListIndexOutOfBoundsAlert(
88                  "First index in slice must be between 1 and the length of the array"
89              ).culprit(
90                  "index",
91                  start
92              ).decorate( objects ).mishap();
93          } else if ( end > objects.length ) {
94              throw new ListIndexOutOfBoundsAlert(
95                  "Last index in slice must not be greater than the length of the array"
96              ).culprit(
97                  "index",
98                  end
99              ).decorate( objects ).mishap();
100         } else {
101             this.store = (V[]) new Object[ end - start + 1 ];
102             try {
103                 System.arraycopy( objects, start - 1, this.store, 0, this.store.length );
104             } catch ( Exception ex ) {
105                 throw new Fault(
106                     "Failed to take a copy of the specified array slice"
107                 ).setParentThrowable( ex ).mishap();
108             } 
109         }
110     }
111 
112     /**
113      * @see java.lang.Object#clone()
114      */
115     @Override
116     public Object clone() throws CloneNotSupportedException {
117         // Nothing special required for this clone
118         return super.clone();
119     }
120 
121     /**
122      * @see org.millscript.commons.util.list.AbstractIList#doGet(int)
123      */
124     @Override
125     protected V doGet( final int pos ) {
126         return this.store[ pos - 1 ];
127     }
128 
129     /**
130      * @see org.millscript.commons.util.list.AbstractIList#doSlice(int, int, boolean)
131      */
132     @Override
133     protected IList< V > doSlice( final int first, final int last, final boolean share ) {
134         if ( share ) {
135             return new ISharedArrayList< V >( this.store, first, last );
136         } else {
137             // Return a copy of the relevant slice of the list
138             return new IArrayList< V >( this.store, first, last );
139         }
140     }
141 
142     /**
143      * @see org.millscript.commons.util.IList#indexOf(java.lang.Object)
144      */
145     public int indexOf( final V value ) {
146         for ( int i = 0; this.store != null && i < this.store.length; i++ ) {
147             if ( value == null ? this.store[ i ] == null : value.equals( this.store[ i ] ) ) {
148                 return i + 1;
149             }
150         }
151         return 0;
152     }
153 
154     /**
155      * @see org.millscript.commons.util.IMap#iterator(boolean)
156      */
157     public ListIterator< V > iterator( final boolean share ) {
158         return new ArrayListIterator< V >( this.store, share );
159     }
160 
161     /**
162      * @see org.millscript.commons.util.IMap#size()
163      */
164     public int size() {
165         return this.store == null ? 0 : this.store.length;
166     }
167 
168     /**
169      * @see org.millscript.commons.util.IList#toArray(null[])
170      */
171     @Override
172     @SuppressWarnings( "unchecked" )
173     public V[] toArray( final V[] target ) {
174         if ( this.size() <= target.length ) {
175             System.arraycopy( this.store, 0, target, 0, this.size() );
176             return target;
177         } else {
178             final V[] dest = (V[]) Array.newInstance(
179                 target.getClass(),
180                 this.size()
181             );
182             System.arraycopy( this.store, 0, dest, 0, this.size() );
183             return dest;
184         }
185     }
186 
187 }