1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 < 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
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
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 }