Bladeren bron

Added a clone() method and implement Cloneable.
Removed whitespace from the ends of lines.

Paul Speed 9 jaren geleden
bovenliggende
commit
c6aac78f42
1 gewijzigde bestanden met toevoegingen van 91 en 73 verwijderingen
  1. 91 73
      jme3-core/src/main/java/com/jme3/util/SafeArrayList.java

+ 91 - 73
jme3-core/src/main/java/com/jme3/util/SafeArrayList.java

@@ -43,7 +43,7 @@ import java.util.*;
  *  the list is changing.</p>
  *
  *  <p>All modifications, including set() operations will cause a copy of the
- *  data to be created that replaces the old version.  Because this list is 
+ *  data to be created that replaces the old version.  Because this list is
  *  not designed for threading concurrency it further optimizes the "many modifications"
  *  case by buffering them as a normal ArrayList until the next time the contents
  *  are accessed.</p>
@@ -63,16 +63,16 @@ import java.util.*;
  *  Even after ListIterator.remove() or Iterator.remove() is called, this change
  *  is not reflected in the iterator instance as it is still refering to its
  *  original snapshot.
- *  </ul>  
+ *  </ul>
  *
  *  @version   $Revision$
  *  @author    Paul Speed
  */
-public class SafeArrayList<E> implements List<E> {
-    
+public class SafeArrayList<E> implements List<E>, Cloneable {
+
     // Implementing List directly to avoid accidentally acquiring
     // incorrect or non-optimal behavior from AbstractList.  For
-    // example, the default iterator() method will not work for 
+    // example, the default iterator() method will not work for
     // this list.
 
     // Note: given the particular use-cases this was intended,
@@ -81,30 +81,48 @@ public class SafeArrayList<E> implements List<E> {
     //       SafeArrayList-specific methods could then be exposed
     //       for the classes like Node and Spatial to use to manage
     //       the list.  This was the callers couldn't remove a child
-    //       without it being detached properly, for example.      
+    //       without it being detached properly, for example.
 
-    private Class<E> elementType; 
+    private Class<E> elementType;
     private List<E> buffer;
     private E[] backingArray;
     private int size = 0;
- 
+
     public SafeArrayList(Class<E> elementType) {
-        this.elementType = elementType;        
+        this.elementType = elementType;
     }
-    
+
     public SafeArrayList(Class<E> elementType, Collection<? extends E> c) {
-        this.elementType = elementType;        
+        this.elementType = elementType;
         addAll(c);
     }
 
+    public SafeArrayList<E> clone() {
+        try {
+            SafeArrayList<E> clone = (SafeArrayList<E>)super.clone();
+
+            // Clone whichever backing store is currently active
+            if( backingArray != null ) {
+                clone.backingArray = backingArray.clone();
+            }
+            if( buffer != null ) {
+                clone.buffer = (List<E>)((ArrayList<E>)buffer).clone();
+            }
+
+            return clone;
+        } catch( CloneNotSupportedException e ) {
+            throw new AssertionError();
+        }
+    }
+
     protected final <T> T[] createArray(Class<T> type, int size) {
-        return (T[])java.lang.reflect.Array.newInstance(type, size);               
+        return (T[])java.lang.reflect.Array.newInstance(type, size);
     }
-    
+
     protected final E[] createArray(int size) {
-        return createArray(elementType, size); 
+        return createArray(elementType, size);
     }
- 
+
     /**
      *  Returns a current snapshot of this List's backing array that
      *  is guaranteed not to change through further List manipulation.
@@ -114,10 +132,10 @@ public class SafeArrayList<E> implements List<E> {
     public final E[] getArray() {
         if( backingArray != null )
             return backingArray;
-            
+
         if( buffer == null ) {
             backingArray = createArray(0);
-        } else {            
+        } else {
             // Only keep the array or the buffer but never both at
             // the same time.  1) it saves space, 2) it keeps the rest
             // of the code safer.
@@ -126,35 +144,35 @@ public class SafeArrayList<E> implements List<E> {
         }
         return backingArray;
     }
- 
+
     protected final List<E> getBuffer() {
         if( buffer != null )
             return buffer;
-            
+
         if( backingArray == null ) {
             buffer = new ArrayList();
-        } else {       
+        } else {
             // Only keep the array or the buffer but never both at
             // the same time.  1) it saves space, 2) it keeps the rest
-            // of the code safer.            
+            // of the code safer.
             buffer = new ArrayList( Arrays.asList(backingArray) );
             backingArray = null;
         }
         return buffer;
     }
-    
+
     public final int size() {
-        return size;            
+        return size;
     }
-    
+
     public final boolean isEmpty() {
         return size == 0;
     }
-    
+
     public boolean contains(Object o) {
         return indexOf(o) >= 0;
     }
-    
+
     public Iterator<E> iterator() {
         return listIterator();
     }
@@ -162,70 +180,70 @@ public class SafeArrayList<E> implements List<E> {
     public Object[] toArray() {
         return getArray();
     }
-    
+
     public <T> T[] toArray(T[] a) {
- 
+
         E[] array = getArray();
         if (a.length < array.length) {
             return (T[])Arrays.copyOf(array, array.length, a.getClass());
-        } 
- 
+        }
+
         System.arraycopy( array, 0, a, 0, array.length );
-        
+
         if (a.length > array.length) {
             a[array.length] = null;
         }
-           
+
         return a;
     }
-    
+
     public boolean add(E e) {
         boolean result = getBuffer().add(e);
         size = getBuffer().size();
         return result;
     }
-    
+
     public boolean remove(Object o) {
         boolean result = getBuffer().remove(o);
         size = getBuffer().size();
         return result;
     }
-    
+
     public boolean containsAll(Collection<?> c) {
         return Arrays.asList(getArray()).containsAll(c);
     }
-    
+
     public boolean addAll(Collection<? extends E> c) {
         boolean result = getBuffer().addAll(c);
         size = getBuffer().size();
         return result;
     }
-    
+
     public boolean addAll(int index, Collection<? extends E> c) {
         boolean result = getBuffer().addAll(index, c);
         size = getBuffer().size();
         return result;
     }
-    
+
     public boolean removeAll(Collection<?> c) {
         boolean result = getBuffer().removeAll(c);
         size = getBuffer().size();
         return result;
     }
-    
+
     public boolean retainAll(Collection<?> c) {
         boolean result = getBuffer().retainAll(c);
         size = getBuffer().size();
         return result;
     }
-    
+
     public void clear() {
         getBuffer().clear();
         size = 0;
     }
-    
+
     public boolean equals(Object o) {
-        if( o == this ) 
+        if( o == this )
             return true;
         if( !(o instanceof List) ) //covers null too
             return false;
@@ -240,9 +258,9 @@ public class SafeArrayList<E> implements List<E> {
             if( o1 == null || !o1.equals(o2) )
                 return false;
         }
-        return !(i1.hasNext() || !i2.hasNext());            
+        return !(i1.hasNext() || !i2.hasNext());
     }
-    
+
     public int hashCode() {
         // Exactly the hash code described in the List interface, basically
         E[] array = getArray();
@@ -252,30 +270,30 @@ public class SafeArrayList<E> implements List<E> {
         }
         return result;
     }
-    
+
     public final E get(int index) {
         if( backingArray != null )
             return backingArray[index];
         if( buffer != null )
             return buffer.get(index);
-        throw new IndexOutOfBoundsException( "Index:" + index + ", Size:0" );        
+        throw new IndexOutOfBoundsException( "Index:" + index + ", Size:0" );
     }
-    
+
     public E set(int index, E element) {
         return getBuffer().set(index, element);
     }
-    
+
     public void add(int index, E element) {
         getBuffer().add(index, element);
         size = getBuffer().size();
     }
-    
+
     public E remove(int index) {
         E result = getBuffer().remove(index);
         size = getBuffer().size();
         return result;
     }
-    
+
     public int indexOf(Object o) {
         E[] array = getArray();
         for( int i = 0; i < array.length; i++ ) {
@@ -289,7 +307,7 @@ public class SafeArrayList<E> implements List<E> {
         }
         return -1;
     }
-    
+
     public int lastIndexOf(Object o) {
         E[] array = getArray();
         for( int i = array.length - 1; i >= 0; i-- ) {
@@ -303,29 +321,29 @@ public class SafeArrayList<E> implements List<E> {
         }
         return -1;
     }
-    
+
     public ListIterator<E> listIterator() {
         return new ArrayIterator<E>(getArray(), 0);
     }
-    
+
     public ListIterator<E> listIterator(int index) {
         return new ArrayIterator<E>(getArray(), index);
     }
-    
+
     public List<E> subList(int fromIndex, int toIndex) {
-    
+
         // So far JME doesn't use subList that I can see so I'm nerfing it.
         List<E> raw =  Arrays.asList(getArray()).subList(fromIndex, toIndex);
         return Collections.unmodifiableList(raw);
     }
- 
+
     public String toString() {
- 
+
         E[] array = getArray();
         if( array.length == 0 ) {
             return "[]";
         }
-        
+
         StringBuilder sb = new StringBuilder();
         sb.append('[');
         for( int i = 0; i < array.length; i++ ) {
@@ -337,63 +355,63 @@ public class SafeArrayList<E> implements List<E> {
         sb.append(']');
         return sb.toString();
     }
- 
+
     protected class ArrayIterator<E> implements ListIterator<E> {
         private E[] array;
         private int next;
         private int lastReturned;
-        
+
         protected ArrayIterator( E[] array, int index ) {
             this.array = array;
             this.next = index;
             this.lastReturned = -1;
         }
-        
+
         public boolean hasNext() {
             return next != array.length;
         }
-        
+
         public E next() {
             if( !hasNext() )
                 throw new NoSuchElementException();
             lastReturned = next++;
             return array[lastReturned];
         }
-        
+
         public boolean hasPrevious() {
-            return next != 0;           
-        }        
-        
+            return next != 0;
+        }
+
         public E previous() {
             if( !hasPrevious() )
                 throw new NoSuchElementException();
             lastReturned = --next;
             return array[lastReturned];
         }
-        
+
         public int nextIndex() {
-            return next;       
+            return next;
         }
-        
+
         public int previousIndex() {
             return next - 1;
         }
-        
+
         public void remove() {
             // This operation is not so easy to do but we will fake it.
             // The issue is that the backing list could be completely
             // different than the one this iterator is a snapshot of.
-            // We'll just remove(element) which in most cases will be 
+            // We'll just remove(element) which in most cases will be
             // correct.  If the list had earlier .equals() equivalent
             // elements then we'll remove one of those instead.  Either
             // way, none of those changes are reflected in this iterator.
             SafeArrayList.this.remove( array[lastReturned] );
         }
-        
+
         public void set(E e) {
             throw new UnsupportedOperationException();
         }
-        
+
         public void add(E e) {
             throw new UnsupportedOperationException();
         }