View Javadoc

1   /**
2    * 
3    */
4   package org.sourceforge.jemm.collections;
5   
6   import java.util.ArrayList;
7   import java.util.Arrays;
8   import java.util.Collection;
9   import java.util.Collections;
10  import java.util.Iterator;
11  import java.util.List;
12  import java.util.ListIterator;
13  
14  import org.sourceforge.jemm.collections.internal.ClearRequest;
15  import org.sourceforge.jemm.collections.internal.ContainsRequest;
16  import org.sourceforge.jemm.collections.internal.ContainsResponse;
17  import org.sourceforge.jemm.collections.internal.RemoveRequest;
18  import org.sourceforge.jemm.collections.internal.RemoveResponse;
19  import org.sourceforge.jemm.collections.internal.SizeRequest;
20  import org.sourceforge.jemm.collections.internal.SizeResponse;
21  import org.sourceforge.jemm.collections.internal.StoredValue;
22  import org.sourceforge.jemm.collections.internal.ToArrayRequest;
23  import org.sourceforge.jemm.collections.internal.ToArrayResponse;
24  import org.sourceforge.jemm.collections.internal.list.ListAddAllRequest;
25  import org.sourceforge.jemm.collections.internal.list.ListAddAllResponse;
26  import org.sourceforge.jemm.collections.internal.list.ListAddRequest;
27  import org.sourceforge.jemm.collections.internal.list.ListAddResponse;
28  import org.sourceforge.jemm.collections.internal.list.ListGetRequest;
29  import org.sourceforge.jemm.collections.internal.list.ListGetResponse;
30  import org.sourceforge.jemm.collections.internal.list.ListIndexOfRequest;
31  import org.sourceforge.jemm.collections.internal.list.ListIndexOfResponse;
32  import org.sourceforge.jemm.collections.internal.list.ListRemoveIndexRequest;
33  import org.sourceforge.jemm.collections.internal.list.ListRemoveIndexResponse;
34  import org.sourceforge.jemm.collections.internal.list.ListSetRequest;
35  import org.sourceforge.jemm.collections.internal.list.ListSetResponse;
36  import org.sourceforge.jemm.collections.internal.list.SubListRequest;
37  import org.sourceforge.jemm.collections.internal.list.SubListResponse;
38  import org.sourceforge.jemm.lifecycle.ShadowTypeObject;
39  import org.sourceforge.jemm.util.JEMMType;
40  
41  /**
42   * Jemm {@link List} implementation.
43   * 
44   * @param <K> The type stored in the list.
45   * @author Rory Graves
46   * 
47   */
48  public final class JemmList<K> extends JEMMType implements List<K>  {
49  
50  	/** Creates a new empty JemmList. */
51      public JemmList() {
52          super();
53      }
54  
55      /** Internally JEMM used constructor
56       * @param jemmOIF The underlying shadow object 
57       */
58      protected JemmList(ShadowTypeObject jemmOIF) {
59      	super(jemmOIF);
60      }
61  
62      public boolean add(K uValue) {
63      	return ((ListAddResponse) jemmOIF.processRequest(new ListAddRequest(new StoredValue(uValue)))).isModified();
64      }
65  
66      public void add(int index, K uValue) {
67      	jemmOIF.processRequest(new ListAddRequest(index,new StoredValue(uValue)));
68      }
69  
70      public boolean addAll(Collection<? extends K> c) {
71      	List<StoredValue> list = new ArrayList<StoredValue>(c.size());
72      	for (Object uValue : c)
73      		list.add(new StoredValue(uValue));
74      	
75      	StoredValue[] values = list.toArray(new StoredValue[0]);
76      	
77          return ((ListAddAllResponse) jemmOIF.processRequest(new ListAddAllRequest(values))).isModified();
78      }
79  
80      public boolean addAll(int index, Collection<? extends K> c) {
81      	List<StoredValue> list = new ArrayList<StoredValue>(c.size());
82      	for (Object uValue : c)
83      		list.add(new StoredValue(uValue));
84      	
85      	StoredValue[] values = list.toArray(new StoredValue[0]);
86      	
87          return ((ListAddAllResponse) jemmOIF.processRequest(new ListAddAllRequest(index,values))).isModified();
88      }
89  
90      public void clear() {
91          jemmOIF.processRequest(new ClearRequest());
92      }
93  
94      public boolean contains(Object value) {
95          ContainsResponse result = (ContainsResponse) jemmOIF.processRequest(new ContainsRequest(value));
96          if(result.isFound())
97          	return true;
98          else
99          	if(result.getPossibles() != null)
100         		for (Object possible : result.getPossibles())
101         			if(value != null && value.equals(possible))
102         				return true;        				
103 		return false;
104     }
105 
106     public boolean containsAll(Collection<?> c) {
107     	throw new UnsupportedOperationException("JemmList does not currently support removeAll()");
108     }
109 
110     @SuppressWarnings("unchecked")
111 	public K get(int index) {
112     	return (K) ((ListGetResponse) jemmOIF.processRequest(new ListGetRequest(index))).getValue();
113     }
114 
115     public int indexOf(Object value) {
116     	return listIndexInternal(value,false);
117     }
118 
119     private int listIndexInternal(Object value, boolean reverse) {
120     	ListIndexOfResponse resp = (ListIndexOfResponse) jemmOIF.processRequest(
121     			new ListIndexOfRequest(new StoredValue(value),reverse));
122     	
123     	if(resp.getIndex() != -1)
124     		return resp.getIndex();
125     	
126     	if(resp.hasPossibles()) {
127     		Object[] possibleValues = resp.getPossibleMatches();
128     		int[] possibleIndexes = resp.getPossibleIndexes();
129     		for(int i=0; i<possibleValues.length; i++)
130     			if(value == possibleValues || value.equals(possibleValues[i]))
131     				return possibleIndexes[i];
132 		}
133     	
134     	return -1;
135 	}
136 
137 	public boolean isEmpty() {
138     	return size() == 0;
139     }
140 
141     public Iterator<K> iterator() {
142     	return listIterator();
143     }
144 
145     public int lastIndexOf(Object uValue) {
146     	return listIndexInternal(uValue, true);
147     }
148 
149     public ListIterator<K> listIterator() {
150     	return listIterator(0);
151     }
152 
153     @SuppressWarnings("unchecked")
154 	public ListIterator<K> listIterator(int index) {
155     	Object[] data = toArray();
156         List<Object> list = new ArrayList<Object>(data.length);
157         for(Object obj : data)
158         	list.add(obj);
159         
160         list = Collections.unmodifiableList(list);
161         return (ListIterator<K>) list.listIterator(index);
162     }
163 
164     public boolean remove(Object uValue) {
165     	
166     	
167     	RemoveRequest req = new RemoveRequest(new StoredValue(uValue));
168     	while(true) {
169     		RemoveResponse resp = (RemoveResponse) jemmOIF.processRequest(req);
170     		if(resp.wasRemoved())
171     			return true;
172     		
173     		if(resp.getPotentialMatches() == null)
174     			return false;
175     		
176     		Object target = null;
177     		for(int i=0; i<resp.getPotentialMatches().length && target == null; i++)
178     			for (Object possible : resp.getPotentialMatches())
179     				if(uValue == possible || (uValue != null && uValue.equals(possible)))
180     					target = possible;
181     		
182     		req = new RemoveRequest(new StoredValue(target));
183     	}
184     }
185 
186     @SuppressWarnings("unchecked")
187 	public K remove(int index) {
188     	return (K) ((ListRemoveIndexResponse) jemmOIF.processRequest(new ListRemoveIndexRequest(index))).getValue();
189     }
190 
191     public boolean removeAll(Collection<?> uCollection) {
192     	throw new UnsupportedOperationException("JemmList does not currently support removeAll()");
193     }
194 
195     public boolean retainAll(Collection<?> uCollection) {
196     	throw new UnsupportedOperationException("JemmList does not currently support retainAll()");
197     }
198 
199     @SuppressWarnings("unchecked")
200 	public K set(int index, K uValue) {
201     	return (K) ((ListSetResponse) jemmOIF.processRequest(
202     			new ListSetRequest(index,new StoredValue(uValue)))).getOldValue();
203     }
204 
205     public int size() {
206     	return ((SizeResponse) jemmOIF.processRequest(new SizeRequest())).getSize();
207     }
208 
209     @SuppressWarnings("unchecked")
210 	public List<K> subList(int fromIndex, int toIndex) {
211     	SubListResponse resp = (SubListResponse) jemmOIF.processRequest(new SubListRequest(fromIndex,toIndex));
212         return (JemmList<K>) resp.getList();
213     }
214 
215     public Object[] toArray() {
216     	return ((ToArrayResponse) jemmOIF.processRequest(new ToArrayRequest())).getArray();
217     }
218 
219     @SuppressWarnings("unchecked")
220 	public <T> T[] toArray(T[] a) {    	
221     	Object[] curValues = toArray();
222     	int size = curValues.length;
223         if (a.length < size) { 
224         	// target array is not large enough
225             // Make a new array of a's runtime type, but my contents:
226             return (T[]) Arrays.copyOf(curValues, size, a.getClass());
227         }
228         
229         System.arraycopy(curValues, 0, a, 0, size);
230         if (a.length > size)
231             a[size] = null;
232         return a;
233     }
234 }