package org.ardverk.dht.storage;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.ardverk.collection.CollectionUtils;
import org.ardverk.dht.rsrc.Value;
import org.ardverk.version.Occured;
import org.ardverk.version.VectorClock;

public class VectorClockMap<K, V extends Value> {
    
    private final List<Entry<K, V>> entries = new ArrayList<Entry<K, V>>();
    
    public void upsert(VectorClock<K> clock, V value) {
        Entry<K, V> entry = new Entry<K, V>(clock, value);
        
        Iterator<Entry<K, V>> it = entries.iterator();
        while (it.hasNext()) {
            Entry<K, V> existing = it.next();
            
            Occured occured = existing.compareTo(clock);
            if (occured == Occured.AFTER) {
                it.remove();
            }
            
            // TODO: What about BEFORE and IDENTICIAL?
        }
        
        entries.add(entry);
    }
    
    public boolean remove(VectorClock<K> clock) {
        if (clock == null && entries.size() == 1) {
            entries.clear();
            return true;
        }
        
        boolean success = false;
        Iterator<Entry<K, V>> it = entries.iterator();
        while (it.hasNext()) {
            Entry<K, V> existing = it.next();
            
            Occured occured = existing.compareTo(clock);
            if (occured == Occured.IDENTICAL) {
                it.remove();
                success = true;
            }
        }
        return success;
    }
    
    public V value() {
        if (!entries.isEmpty()) {
            Entry<?, V> entry = CollectionUtils.last(entries);
            return entry.value;
        }
        return null;
    }
    
    public Value[] values() {
        Value[] values = new Value[entries.size()];
        int index = 0;
        for (Entry<?, V> entry : entries) {
            values[index++] = entry.value;
        }
        return values;
    }
    
    public int size() {
        return entries.size();
    }
    
    public boolean isEmpty() {
        return size() == 0;
    }
    
    private static class Entry<K, V extends Value> {
        
        private final VectorClock<K> clock;
        
        private final V value;
        
        public Entry(VectorClock<K> clock, V value) {
            this.clock = clock;
            this.value = value;
        }
        
        public Occured compareTo(VectorClock<K> other) {
            return VectorClockUtils.compare(clock, other);
        }
    }
}

@@ -44,25 +44,24 @@
 va.util.
-ArrayList
+Iterator
 ;%0Aimport
@@ -67,32 +67,37 @@
 t java.util.
-Iterator
+LinkedHashMap
 ;%0Aimport jav
@@ -103,20 +103,19 @@
 va.util.
-List
+Map
 ;%0A%0Aimpor
@@ -345,62 +345,82 @@
 nal 
-List%3CEntry
+Map%3CVectorClock
 %3CK
+%3E
 , V%3E
-%3E entries = new ArrayList%3CEntry
+ map %0A        = new LinkedHashMap%3CVectorClock
 %3CK
+%3E
 , V%3E
-%3E
 ();%0A
@@ -454,37 +454,35 @@
 (VectorClock%3CK%3E 
-clock
+key
 , V value) %7B%0A   
@@ -490,110 +490,59 @@
     
-Entry%3CK, V%3E entry = new Entry%3CK, V%3E(clock, value);%0A        %0A        Iterator%3CEntry%3CK, V%3E%3E it = entries
+%0A        Iterator%3CVectorClock%3CK%3E%3E it = map.keySet()
 .ite
@@ -589,34 +589,37 @@
             
-Entry%3CK, V
+VectorClock%3CK
 %3E existing =
@@ -677,32 +677,46 @@
 d = 
-existing.compareTo(clock
+VectorClockUtils.compare(existing, key
 );%0A 
@@ -718,34 +718,38 @@
 y);%0A            
-if
+switch
  (occured == Occ
@@ -745,29 +745,44 @@
 ured
- == Occured.AFTER) %7B%0A
+) %7B%0A                case AFTER:%0A    
     
@@ -818,26 +818,24 @@
         
-%7D%0A
         
     %0A   
@@ -818,36 +818,38 @@
                 
-    
+break;
 %0A            // 
@@ -849,50 +849,9 @@
     
-// TODO: What about BEFORE and IDENTICIAL?
+%7D
 %0A   
@@ -878,25 +878,26 @@
     
-entries.add(entry
+map.put(key, value
 );%0A 
@@ -951,962 +951,230 @@
 %3CK%3E 
-clock) %7B%0A        if (clock == null && entries.size() == 1) %7B%0A            entries.clear();%0A            return true;%0A        %7D%0A        %0A        boolean success = false;%0A        Iterator%3CEntry%3CK, V%3E%3E it = entries.iterator();%0A        while (it.hasNext()) %7B%0A            Entry%3CK, V%3E existing = it.next();%0A            %0A            Occured occured = existing.compareTo(clock);%0A            if (occured == Occured.IDENTICAL) %7B%0A                it.remove();%0A                success = true;%0A            %7D%0A        %7D%0A        return success;%0A    %7D%0A    %0A    public V value() %7B%0A        if (!entries.isEmpty()) %7B%0A            Entry%3C?, V%3E entry = CollectionUtils.last(entries);%0A            return entry.value;%0A        %7D%0A        return null;%0A    %7D%0A    %0A    public Value%5B%5D values() %7B%0A        Value%5B%5D values = new Value%5Bentries.size()%5D;%0A        int index = 0;%0A        for (Entry%3C?, V%3E entry : entries) %7B%0A            values%5Bindex++%5D = entry.value;%0A        %7D%0A        return values
+key) %7B%0A        return map.remove(key) != null;%0A    %7D%0A    %0A    public V value() %7B%0A        return CollectionUtils.last(map.values());%0A    %7D%0A    %0A    public Value%5B%5D values() %7B%0A        return map.values().toArray(new Value%5B0%5D)
 ;%0A  
@@ -1225,15 +1225,11 @@
 urn 
-entries
+map
 .siz
@@ -1294,449 +1294,22 @@
 urn 
-size() == 0;%0A    %7D%0A    %0A    private static class Entry%3CK, V extends Value%3E %7B%0A        %0A        private final VectorClock%3CK%3E clock;%0A        %0A        private final V value;%0A        %0A        public Entry(VectorClock%3CK%3E clock, V value) %7B%0A            this.clock = clock;%0A            this.value = value;%0A        %7D%0A        %0A        public Occured compareTo(VectorClock%3CK%3E other) %7B%0A            return VectorClockUtils.compare(clock, other);%0A        %7D
+map.isEmpty();
 %0A   

Use LinkedHashMap