View Javadoc

1   /*
2    * $Id: ArrayIndexesModel.java,v 1.18 2011/06/16 09:29:41 jbmeslin Exp $
3    * 
4    */
5   package org.rcfaces.core.internal.tools;
6   
7   import java.io.Serializable;
8   import java.util.Arrays;
9   import java.util.HashSet;
10  import java.util.Set;
11  
12  import org.apache.commons.logging.Log;
13  import org.apache.commons.logging.LogFactory;
14  import org.rcfaces.core.model.AbstractIndexesModel;
15  import org.rcfaces.core.model.ICommitableObject;
16  import org.rcfaces.core.model.IIndexesModel;
17  
18  /**
19   * @author Olivier Oeuillot (latest modification by $Author: jbmeslin $)
20   * @version $Revision: 1.18 $ $Date: 2011/06/16 09:29:41 $
21   */
22  public class ArrayIndexesModel extends AbstractIndexesModel implements
23          Serializable, ICommitableObject {
24      private static final String REVISION = "$Revision: 1.18 $";
25  
26      private static final long serialVersionUID = 7393822820762985697L;
27  
28      private static final Log LOG = LogFactory.getLog(ArrayIndexesModel.class);
29  
30      protected static final int[] EMPTY_SELECTION = new int[0];
31  
32      private static final boolean VERIFY_GARBAGE = LOG.isDebugEnabled();
33      static {
34          if (VERIFY_GARBAGE) {
35              LOG.info("Verify GARBAGE enabled");
36          }
37      }
38  
39      private int selectionIndexes[] = EMPTY_SELECTION;
40  
41      private int lastPos = 0;
42  
43      private int count = 0;
44  
45      private boolean garbaged = true;
46  
47      private boolean commited;
48  
49      public ArrayIndexesModel() {
50      }
51  
52      public ArrayIndexesModel(int[] indexes) {
53          setIndexes(indexes, false);
54      }
55  
56      public int[] listSortedIndexes() {
57          if (count == 0) {
58              return EMPTY_SELECTION;
59          }
60  
61          garbage();
62  
63          int a[] = new int[count];
64          System.arraycopy(selectionIndexes, 0, a, 0, count);
65  
66          Arrays.sort(a);
67  
68          return a;
69      }
70  
71      public int getFirstIndex() {
72          if (count == 0) {
73              return -1;
74          }
75  
76          garbage();
77  
78          return selectionIndexes[0];
79      }
80  
81      private void garbage() {
82          if (garbaged) {
83              return;
84          }
85  
86          garbaged = true;
87          if (count == lastPos) {
88              return;
89          }
90  
91          int lastEmpty = -1;
92          int last = -1;
93          for (int i = 0; i < lastPos; i++) {
94              int n = selectionIndexes[i];
95  
96              if (n < 0) {
97                  if (lastEmpty < 0) {
98                      lastEmpty = i;
99                  }
100 
101                 continue;
102             }
103 
104             if (lastEmpty >= 0) {
105                 selectionIndexes[lastEmpty] = n;
106                 last = lastEmpty;
107                 lastEmpty++;
108                 continue;
109             }
110 
111             last = i;
112 
113             continue;
114         }
115 
116         // Assure que count==last
117         if (count != last + 1) {
118             LOG.error("Y a un probleme ! (count!=last)");
119         }
120 
121         if (VERIFY_GARBAGE) {
122             Set set = new HashSet(count);
123             for (int i = 0; i < count; i++) {
124                 if (set.add(new Integer(i)) == false) {
125                     LOG.error("Y a un GROS probleme avec le garbage !");
126                 }
127             }
128         }
129 
130         lastPos = count;
131     }
132 
133     /*
134      * (non-Javadoc)
135      * 
136      * @see org.rcfaces.core.model.ISelectionModel#clearSelections()
137      */
138     public void clearIndexes() {
139         if (commited) {
140             throw new IllegalStateException("Already commited indexes model.");
141         }
142         count = 0;
143         lastPos = 0;
144         garbaged = true;
145     }
146 
147     /*
148      * (non-Javadoc)
149      * 
150      * @see org.rcfaces.core.model.ISelectionModel#isSelected(int)
151      */
152     public boolean containsIndex(int index) {
153         if (index < 0) {
154             throw new IllegalArgumentException("Invalid index (" + index
155                     + " < 0)");
156         }
157 
158         if (count == 0) {
159             return false;
160         }
161 
162         garbage();
163 
164         for (int i = 0; i < count; i++) {
165             int n = selectionIndexes[i];
166 
167             if (index == n) {
168                 return true;
169             }
170         }
171 
172         return false;
173     }
174 
175     /*
176      * (non-Javadoc)
177      * 
178      * @see org.rcfaces.core.model.ISelectionModel#addSelection(int)
179      */
180     public boolean addIndex(int index) {
181         if (commited) {
182             throw new IllegalStateException("Already commited indexes model.");
183         }
184 
185         if (index < 0) {
186             throw new IllegalArgumentException("Invalid index (" + index
187                     + " < 0)");
188         }
189 
190         for (int i = 0; i < lastPos; i++) {
191             int n = selectionIndexes[i];
192 
193             if (index == n) {
194                 return false;
195             }
196         }
197 
198         if (lastPos < selectionIndexes.length) {
199             selectionIndexes[lastPos++] = index;
200             count++;
201             garbaged = false;
202             return true;
203         }
204 
205         garbage();
206 
207         if (lastPos < selectionIndexes.length) {
208             selectionIndexes[lastPos++] = index;
209             count++;
210             garbaged = false;
211             return true;
212         }
213 
214         // On agrandi
215         int d = count / 2;
216         if (d < 8) {
217             d = 8;
218         }
219         int n[] = new int[count + d];
220         if (count > 0) {
221             System.arraycopy(selectionIndexes, 0, n, 0, count);
222         }
223 
224         selectionIndexes = n;
225 
226         selectionIndexes[lastPos++] = index;
227         count++;
228         garbaged = false;
229 
230         return true;
231     }
232 
233     /*
234      * (non-Javadoc)
235      * 
236      * @see org.rcfaces.core.model.ISelectionModel#removeSelection(int)
237      */
238     public boolean removeIndex(int index) {
239         if (commited) {
240             throw new IllegalStateException("Already commited indexes model.");
241         }
242 
243         if (index < 0) {
244             throw new IllegalArgumentException("Invalid index (" + index
245                     + " < 0)");
246         }
247         if (count == 0) {
248             return false;
249         }
250 
251         for (int i = 0; i < lastPos; i++) {
252             if (selectionIndexes[i] != index) {
253                 continue;
254             }
255 
256             selectionIndexes[i] = -1;
257             count--;
258             garbaged = false;
259             return true;
260         }
261 
262         return false;
263     }
264 
265     /*
266      * (non-Javadoc)
267      * 
268      * @see org.rcfaces.core.model.IIndexesModel#setIndexes(int[])
269      */
270     public void setIndexes(int[] indexes) {
271         setIndexes(indexes, true);
272     }
273 
274     public void setIndexes(int[] indexes, boolean copy) {
275         if (commited) {
276             throw new IllegalStateException("Already commited indexes model.");
277         }
278 
279         if (indexes == null || indexes.length < 1) {
280             selectionIndexes = EMPTY_SELECTION;
281             lastPos = 0;
282             count = 0;
283             return;
284         }
285 
286         if (copy) {
287             selectionIndexes = new int[indexes.length];
288             System.arraycopy(indexes, 0, selectionIndexes, 0, indexes.length);
289 
290         } else {
291             selectionIndexes = indexes;
292         }
293 
294         garbaged = true;
295         count = selectionIndexes.length;
296         lastPos = count;
297 
298         for (int i = 0; i < selectionIndexes.length; i++) {
299             if (selectionIndexes[i] >= 0) {
300                 continue;
301             }
302 
303             garbaged = false;
304             count--;
305         }
306     }
307 
308     /*
309      * (non-Javadoc)
310      * 
311      * @see org.rcfaces.core.model.IIndexesModel#countIndexes()
312      */
313     public int countIndexes() {
314         return count;
315     }
316 
317     public IIndexesModel copy() {
318         garbage();
319 
320         if (LOG.isDebugEnabled()) {
321             LOG.debug("Copy model");
322         }
323 
324         return new ArrayIndexesModel(selectionIndexes);
325     }
326 
327     public void commit() {
328         garbage();
329 
330         if (LOG.isDebugEnabled()) {
331             LOG.debug("Commit model");
332         }
333 
334         commited = true;
335     }
336 
337     public boolean isCommited() {
338         return commited;
339     }
340 
341 }