Ranides Atterwim пре 9 година
родитељ
комит
23ada1e36b

+ 18 - 0
assira.drafts/src/main/java/net/ranides/assira/collections/map/IndexComparator.java

@@ -0,0 +1,18 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira.drafts
+ */
+package net.ranides.assira.collections.map;
+
+import java.util.function.Function;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public interface IndexComparator<V,T> extends Function<V,T>  {
+
+    
+}

+ 9 - 3
assira.drafts/src/main/java/net/ranides/assira/collections/map/IndexMap.java

@@ -15,11 +15,15 @@ import java.util.Comparator;
  */
 public interface IndexMap<V> {
 
-    IndexMap<V> index(String name, Comparator<? super V> index);
+    IndexMap<V> index(String name, Comparator<V> index);
+    
+    <T> IndexMap<V> index(String name, IndexComparator<V,T> index);
     
     IndexQuery<V> find();
 
-    IndexQuery<V> find(Comparator<? super V> index, V value);
+    IndexQuery<V> find(Comparator<V> index, V value);
+    
+    <T> IndexQuery<V> find(IndexComparator<V,T> index, T value);
 
     IndexQuery<V> find(String index, V value);
 
@@ -27,7 +31,9 @@ public interface IndexMap<V> {
 
     void put(Collection<? extends V> values);
 
-    void remove(Comparator<? super V> index, V value);
+    void remove(Comparator<V> index, V value);
+    
+    <T> void remove(IndexComparator<V,T> index, T value);
 
     void remove(String index, V value);
     

+ 16 - 8
assira.drafts/src/main/java/net/ranides/assira/collections/map/IndexQuery.java

@@ -16,24 +16,32 @@ import net.ranides.assira.collection.query.CQuery;
  */
 public interface IndexQuery<V> extends CQuery<V> {
 
-    IndexQuery<V> eq(Comparator<? super V> index, V value);
+    IndexQuery<V> eq(Comparator<V> index, V value);
+    
+    <T> IndexQuery<V> eq(IndexComparator<V,T> index, T value);
 
-    IndexQuery<V> eq(String index, V value);
+    IndexQuery<V> eq(String index, Object value);
     
 
-    IndexQuery<V> gt(Comparator<? super V> index, V value);
+    IndexQuery<V> gt(Comparator<V> index, V value);
+    
+    <T> IndexQuery<V> gt(IndexComparator<V,T> index, T value);
 
-    IndexQuery<V> gt(String index, V value);
+    IndexQuery<V> gt(String index, Object value);
     
     
-    IndexQuery<V> lt(Comparator<? super V> index, V value);
+    IndexQuery<V> lt(Comparator<V> index, V value);
+    
+    <T> IndexQuery<V> lt(IndexComparator<V,T> index, T value);
 
-    IndexQuery<V> lt(String index, V value);
+    IndexQuery<V> lt(String index, Object value);
     
 
-    IndexQuery<V> in(Comparator<? super V> index, V begin, V end);
+    IndexQuery<V> in(Comparator<V> index, V begin, V end);
+    
+    <T> IndexQuery<V> in(IndexComparator<V,T> index, T begin, T end);
 
-    IndexQuery<V> in(String index, V begin, V end);
+    IndexQuery<V> in(String index, Object begin, Object end);
 
     
     void remove();

+ 26 - 13
assira.drafts/src/main/java/net/ranides/assira/collections/map/impl/AIndexMap.java

@@ -9,6 +9,7 @@ package net.ranides.assira.collections.map.impl;
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.function.Consumer;
+import net.ranides.assira.collections.map.IndexComparator;
 import net.ranides.assira.collections.map.IndexMap;
 import net.ranides.assira.collections.map.IndexQuery;
 
@@ -17,17 +18,24 @@ import net.ranides.assira.collections.map.IndexQuery;
  * @author Ranides Atterwim <ranides@gmail.com>
  */
 public abstract class AIndexMap<V> implements IndexMap<V> {
+
+    @Override
+    public abstract AIndexQuery<V> find();
     
-    
     @Override
-    public final IndexQuery<V> find(Comparator<? super V> index, V value) {
-        return find().eq(index, value);
+    public final IndexQuery<V> find(Comparator<V> index, V value) {
+        return find().$eq(index, value);
+    }
+
+    @Override
+    public <T> IndexQuery<V> find(IndexComparator<V, T> index, T value) {
+        return find().$eq(index, value);
     }
     
     @SuppressWarnings("unchecked")
     @Override
-    public final IndexQuery<V> find(String index, V value) {
-        return find().eq(indexForName(index), value);
+    public final IndexQuery<V> find(String index, Object value) {
+        return find().$eq($index(index), value);
     }
     
     @Override
@@ -38,13 +46,18 @@ public abstract class AIndexMap<V> implements IndexMap<V> {
     }
     
     @Override
-    public final void remove(Comparator<? super V> index, V value) {
-        find(index, value).remove();
+    public final void remove(Comparator<V> index, V value) {
+        find().$eq(index, value).remove();
+    }
+
+    @Override
+    public <T> void remove(IndexComparator<V, T> index, T value) {
+        find().$eq(index, value).remove();
     }
     
     @Override
-    public final void remove(String index, V value) {
-        find(index, value).remove();
+    public final void remove(String index, Object value) {
+        find().$eq(index, value).remove();
     }
 
     @Override
@@ -54,10 +67,10 @@ public abstract class AIndexMap<V> implements IndexMap<V> {
         }
     }
     
-    protected abstract Comparator indexForName(String name);
-
-    protected abstract void update(V value, Consumer<? super V> consumer);
+    protected abstract Object $index(String name);
+    
+    protected abstract void $update(V value, Consumer<? super V> consumer);
     
-    protected abstract void updateAll();
+    protected abstract void $update();
     
 }

+ 62 - 9
assira.drafts/src/main/java/net/ranides/assira/collections/map/impl/AIndexQuery.java

@@ -7,11 +7,14 @@
 package net.ranides.assira.collections.map.impl;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
 import java.util.List;
 import net.ranides.assira.collections.map.IndexQuery;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import net.ranides.assira.collection.query.CQueryAbstract;
+import net.ranides.assira.collections.map.IndexComparator;
 
 /**
  *
@@ -22,28 +25,78 @@ public abstract class AIndexQuery<V> extends CQueryAbstract<V> implements IndexQ
     protected abstract AIndexMap<V> parent();
     
     @Override
-    public final IndexQuery<V> eq(String index, V value) {
-        return eq(parent().indexForName(index), value);
+    public final IndexQuery<V> eq(String index, Object value) {
+        return $eq(parent().$index(index), value);
+    }
+
+    @Override
+    public IndexQuery<V> eq(Comparator<V> index, V value) {
+        return $eq(index, value);
+    }
+
+    @Override
+    public <T> IndexQuery<V> eq(IndexComparator<V, T> index, T value) {
+        return $eq(index, value);
+    }
+    
+    @Override
+    public final IndexQuery<V> lt(String index, Object value) {
+        return $lt(parent().$index(index), value);
+    }
+    
+    @Override
+    public IndexQuery<V> lt(Comparator<V> index, V value) {
+        return $lt(index, value);
+    }
+
+    @Override
+    public <T> IndexQuery<V> lt(IndexComparator<V, T> index, T value) {
+        return $lt(index, value);
+    }
+    
+    @Override
+    public final IndexQuery<V> gt(String index, Object value) {
+        return $gt(parent().$index(index), value);
     }
     
     @Override
-    public final IndexQuery<V> lt(String index, V value) {
-        return lt(parent().indexForName(index), value);
+    public IndexQuery<V> gt(Comparator<V> index, V value) {
+        return $gt(index, value);
+    }
+
+    @Override
+    public <T> IndexQuery<V> gt(IndexComparator<V, T> index, T value) {
+        return $gt(index, value);
     }
     
     @Override
-    public final IndexQuery<V> gt(String index, V value) {
-        return gt(parent().indexForName(index), value);
+    public final IndexQuery<V> in(String index, Object begin, Object end) {
+        return $in(parent().$index(index), begin, end);
     }
     
     @Override
-    public final IndexQuery<V> in(String index, V begin, V end) {
-        return in(parent().indexForName(index), begin, end);
+    public IndexQuery<V> in(Comparator<V> index, V begin, V end) {
+        return $in(index, begin, end);
+    }
+
+    @Override
+    public <T> IndexQuery<V> in(IndexComparator<V, T> index, T begin, T end) {
+        return $in(index, begin, end);
     }
     
     @Override
     public void update(Consumer<? super V> consumer) {
-        collect(Collectors.toList()).forEach(v -> parent().update(v, consumer));
+        $select().forEach(v -> parent().$update(v, consumer));
     }
     
+    protected abstract Collection<V> $select();
+            
+    protected abstract IndexQuery<V> $eq(Object index, Object value);
+    
+    protected abstract IndexQuery<V> $lt(Object index, Object value);
+    
+    protected abstract IndexQuery<V> $gt(Object index, Object value);
+    
+    protected abstract IndexQuery<V> $in(Object index, Object begin, Object end);
+    
 }

+ 120 - 35
assira.drafts/src/main/java/net/ranides/assira/collections/map/impl/CIndexTreeMap.java

@@ -14,12 +14,17 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.SortedMap;
 import java.util.SortedSet;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
+import net.ranides.assira.collection.maps.ASortedMap;
+import net.ranides.assira.collection.maps.RBTreeMultiMap;
 import net.ranides.assira.collection.sets.ASortedSet;
 import net.ranides.assira.collection.sets.RBTreeMultiSet;
+import net.ranides.assira.collections.map.IndexComparator;
 import net.ranides.assira.collections.map.IndexMap;
 import net.ranides.assira.collections.map.IndexQuery;
 import net.ranides.assira.generic.CompareUtils;
@@ -30,15 +35,17 @@ import net.ranides.assira.generic.CompareUtils;
  */
 public class CIndexTreeMap<V> extends AIndexMap<V> {
     
-    private final Map<String, Comparator> name2cmp = new HashMap<>();
+    private final Map<String, Object> name2index = new HashMap<>();
     
-    private final Map<Comparator, ASortedSet<V>> indexes = new HashMap<>();
+    private final Map<Comparator, ASortedSet<V>> cindexes = new HashMap<>();
+    
+    private final Map<IndexComparator, RBTreeMultiMap<Object, V>> mindexes = new HashMap<>();
 
     @Override
-    public IndexMap<V> index(String name, Comparator<? super V> index) {
+    public IndexMap<V> index(String name, Comparator<V> index) {
         RBTreeMultiSet<V> set = new RBTreeMultiSet<>(index);
-        indexes.put(index, set);
-        name2cmp.put(name, index);
+        cindexes.put(index, set);
+        name2index.put(name, index);
         for(V item : values()) {
             set.add(item);
         }
@@ -46,12 +53,23 @@ public class CIndexTreeMap<V> extends AIndexMap<V> {
     }
 
     @Override
-    protected Comparator indexForName(String name) {
-        return name2cmp.get(name);
+    public <T> IndexMap<V> index(String name, IndexComparator<V, T> index) {
+        RBTreeMultiMap<Object,V> map = new RBTreeMultiMap<>();
+        mindexes.put(index, map);
+        name2index.put(name, index);
+        for(V item : values()) {
+            map.put(index.apply(item),item);
+        }
+        return this;
+    }
+
+    @Override
+    protected Object $index(String name) {
+        return name2index.get(name);
     }
 
     @Override
-    protected void update(V value, Consumer<? super V> consumer) {
+    protected void $update(V value, Consumer<? super V> consumer) {
         remove(value);
         consumer.accept(value);
         put(value);
@@ -59,12 +77,15 @@ public class CIndexTreeMap<V> extends AIndexMap<V> {
     
     @Override
     public void remove(V value) {
-        for(SortedSet<V> index : indexes.values()) {
-            iremove(index, value);
+        for(SortedSet<V> index : cindexes.values()) {
+            $remove(index, value);
+        }
+        for(SortedMap<Object,V> index : mindexes.values()) {
+            CIndexTreeMap.this.$remove(index, value);
         }
     }
     
-    void iremove(SortedSet<V> set, V value) {
+    void $remove(SortedSet<V> set, V value) {
         Comparator<? super V> c = set.comparator();
         Iterator<V> i = set.headSet(value).iterator();
         while(i.hasNext()) {
@@ -79,37 +100,80 @@ public class CIndexTreeMap<V> extends AIndexMap<V> {
         }
     }
     
+    void $remove(SortedMap<Object,V> map, V value) {
+        Comparator<Object> c = CompareUtils.comparator();
+        Iterator<Entry<Object,V>> i = map.headMap(value).entrySet().iterator();
+        while(i.hasNext()) {
+            Entry<Object,V> item = i.next();
+            if(c.compare(item.getKey(), value) !=0) {
+                return;
+            }
+            if(CompareUtils.equals(item.getValue(),value)) {
+                i.remove();
+                return;
+            }
+        }
+    }
+    
     @Override
-    protected void updateAll() {
+    protected void $update() {
         List<V> items = new ArrayList<>(values());
-        for(SortedSet<V> index : indexes.values()) {
+        for(SortedSet<V> index : cindexes.values()) {
             index.clear();
             index.addAll(items);
         }
+        for(Entry<IndexComparator, RBTreeMultiMap<Object,V>> entry : mindexes.entrySet()) {
+            IndexComparator fun = entry.getKey();
+            RBTreeMultiMap<Object, V> index = entry.getValue();
+            index.clear();
+            for(V item : items) {
+                index.put(fun.apply(item), item);
+            }
+        }
     }
 
     
     @Override
-    public IndexQuery<V> find() {
+    public AIndexQuery<V> find() {
         return new CHQuery();
     }
 
     @Override
     public void put(V value) {
-        for(SortedSet<V> index : indexes.values()) {
+        for(SortedSet<V> index : cindexes.values()) {
             index.add(value);
         }
+        for(Entry<IndexComparator, RBTreeMultiMap<Object,V>> entry : mindexes.entrySet()) {
+            IndexComparator fun = entry.getKey();
+            RBTreeMultiMap<Object, V> index = entry.getValue();
+            index.put(fun.apply(value), value);
+        }
     }
 
     @Override
     public void clear() {
-        for(SortedSet<V> index : indexes.values()) {
+        for(SortedSet<V> index : cindexes.values()) {
             index.clear();
         }
     }
     
-    private ASortedSet<V> values() {
-        return indexes.values().iterator().next();
+    private Collection<V> values() {
+        if(cindexes.isEmpty()) {
+            return Collections.emptySet();
+        }
+        return cindexes.values().iterator().next();
+    }
+
+    private Object after(ASortedMap<Object, V> map, Object value) {
+        Comparator<Object> cmp = map.comparator();
+        Iterator<Object> i = map.keySet().iterator(value);
+        while(i.hasNext()) {
+            Object next = i.next();
+            if(!CompareUtils.equals(value, next)) {
+                return next;
+            }
+        }
+        return null;
     }
 
     
@@ -134,49 +198,70 @@ public class CIndexTreeMap<V> extends AIndexMap<V> {
 
         @Override
         public Stream<V> stream() {
-            return select().stream();
+            return $select().stream();
         }
 
         @Override
         public int size() {
-            return select().size();
+            return $select().size();
         }
 
         @Override
         public Iterator<V> iterator() {
-            return select().iterator();
+            return $select().iterator();
         }
 
         @Override
-        public IndexQuery<V> eq(Comparator<? super V> index, V value) {
-            return new CHQuery(this, () -> indexes.get(index).getAll(value));
+        public IndexQuery<V> $eq(Object index, Object value) {
+            if(index instanceof Comparator) {
+                return new CHQuery(this, () -> cindexes.get(index).getAll((V)value));
+            } else {
+                return new CHQuery(this, () -> mindexes.get(index).getAll(value));
+            }
         }
 
         @Override
-        public IndexQuery<V> gt(Comparator<? super V> index, V value) {
-            ASortedSet<V> set = indexes.get(index);
-            return new CHQuery(this, () -> {
-                V last = set.after(value);
-                return last==null ? Collections.emptyList() : set.tailSet(last);
-            });
+        public IndexQuery<V> $gt(Object index, Object value) {
+            if(index instanceof Comparator) {
+                ASortedSet<V> set = cindexes.get(index);
+                return new CHQuery(this, () -> {
+                    V last = set.after((V)value);
+                    return last==null ? Collections.emptyList() : set.tailSet(last);
+                });
+            } else {
+                RBTreeMultiMap<Object, V> map = mindexes.get(index);
+                return new CHQuery(this, () -> {
+                    Object last = after(map,value);
+                    return last==null ? Collections.emptyList() : map.tailMap(last).values();
+                });
+            }
         }
 
         @Override
-        public IndexQuery<V> lt(Comparator<? super V> index, V value) {
-            return new CHQuery(this, () -> indexes.get(index).headSet(value));
+        public IndexQuery<V> $lt(Object index, Object value) {
+            if(index instanceof Comparator) {
+                return new CHQuery(this, () -> cindexes.get(index).headSet((V)value));
+            } else {
+                return new CHQuery(this, () -> mindexes.get(index).headMap(value).values());
+            }
         }
 
         @Override
-        public IndexQuery<V> in(Comparator<? super V> index, V begin, V end) {
-            return new CHQuery(this, () -> indexes.get(index).subSet(begin, end));
+        public IndexQuery<V> $in(Object index, Object begin, Object end) {
+            if(index instanceof Comparator) {
+                return new CHQuery(this, () -> cindexes.get(index).subSet((V)begin, (V)end));
+            } else {
+                return new CHQuery(this, () -> mindexes.get(index).subMap((V)begin, (V)end).values());
+            }
         }
 
         @Override
         public void remove() {
-            removeAll(select());
+            removeAll($select());
         }
         
-        private List<V> select() {
+        @Override
+        protected Collection<V> $select() {
             int psize = 0;
             Collection<V> prim = null;
             List<Collection<V>> sec = new ArrayList<>(selectors.size()-1);

+ 143 - 1
assira.drafts/src/test/java/net/ranides/assira/collections/map/impl/CIndexTreeMapTest.java

@@ -10,6 +10,7 @@ import net.ranides.assira.collections.map.IndexMap;
 import net.ranides.assira.generic.CompareUtils;
 import org.junit.Test;
 import static org.junit.Assert.*;
+import org.junit.Ignore;
 
 /**
  *
@@ -17,10 +18,12 @@ import static org.junit.Assert.*;
  */
 public class CIndexTreeMapTest {
     
+    @Ignore
     @Test
-    public void testBasic() {
+    public void testSetIndex() {
         
         IndexMap<Person> db = new CIndexTreeMap<>();
+        
         db.index("name", (a,b) -> CompareUtils.cmp(a.name, b.name));
         db.index("surname", (a,b) -> CompareUtils.cmp(a.surname, b.surname));
         db.index("age", (a,b) -> CompareUtils.cmp(a.age, b.age));
@@ -157,6 +160,145 @@ public class CIndexTreeMapTest {
         );
     }
     
+    @Test
+    public void testMapIndex() {
+        
+        IndexMap<Person> db = new CIndexTreeMap<>();
+        
+        db.index("name", a -> a.name);
+        db.index("surname", a -> a.surname);
+        db.index("age", a -> a.age);
+        
+        db.put(new Person("Tom", "A", 17));
+        db.put(new Person("Tom", "B", 23));
+        db.put(new Person("Joe", "A", 20));
+        db.put(new Person("Helene", "C", 19));
+        db.put(new Person("Andrew", "S", 23));
+        db.put(new Person("Helene", "C", 23));
+        db.put(new Person("George", "T", 17));
+        db.put(new Person("Peter", "A", 17));
+        
+        System.out.printf("RESULT = %s%n", db.find()
+            .eq("name", "Helene")
+            .sort()
+            .list()
+        );
+        System.out.printf("RESULT = %s%n", db.find()
+            .eq("age", 23)
+            .sort()
+            .list()
+        );
+        System.out.printf("RESULT = %s%n", db.find()
+            .eq("name", "Helene")
+            .eq("age", 23)
+            .sort()
+            .list()
+        );
+        System.out.printf("RESULT = %s%n", db.find()
+            .eq("age", 17)
+            .sort()
+            .list()
+        );
+        System.out.printf("RESULT = %s%n", db.find()
+            .eq("surname", "A")
+            .eq("age", 17)
+            .sort()    
+            .list()
+        );
+        System.out.printf("RESULT = %s%n", db.find()
+            .gt("age", 17)
+            .sort()
+            .list()
+        );
+        System.out.printf("RESULT = %s%n", db.find()
+            .gt("age", 40)
+            .sort()
+            .list()
+        );
+        System.out.printf("RESULT = %s%n", db.find()
+            .lt("age", 18)
+            .sort()
+            .list()
+        );
+        System.out.printf("RESULT = %s%n", db.find()
+            .lt("age", 17)
+            .sort()
+            .list()
+        );
+        System.out.printf("RESULT = %s%n", db.find()
+            .eq("name", "Helene")
+            .lt("age", 23)
+            .sort()
+            .list()
+        );
+        
+        
+        
+        assertEquals("[{Helene C 19}, {Helene C 23}]", db.find()
+            .eq("name", "Helene")
+            .sort()
+            .list()
+            .toString()
+        );
+        assertEquals("[{Tom B 23}, {Helene C 23}, {Andrew S 23}]", db.find()
+            .eq("age", 23)
+            .sort()
+            .list()
+            .toString()
+        );
+        assertEquals("[{Helene C 23}]", db.find()
+            .eq("name", "Helene")
+            .eq("age", 23)
+            .sort()
+            .list()
+            .toString()
+        );
+        assertEquals("[{Peter A 17}, {Tom A 17}, {George T 17}]", db.find()
+            .eq("age", 17)
+            .sort()
+            .list()
+            .toString()
+        );
+        assertEquals("[{Peter A 17}, {Tom A 17}]", db.find()
+            .eq("surname", "A")
+            .eq("age", 17)
+            .sort()    
+            .list()
+            .toString()
+        );
+        assertEquals("[{Joe A 20}, {Tom B 23}, {Helene C 19}, {Helene C 23}, {Andrew S 23}]", db.find()
+            .gt("age", 17)
+            .sort()
+            .list()
+            .toString()
+        );
+        assertEquals("[]", db.find()
+            .gt("age", 40)
+            .sort()
+            .list()
+            .toString()
+        );
+        assertEquals("[{Peter A 17}, {Tom A 17}, {George T 17}]", db.find()
+            .lt("age", 18)
+            .sort()
+            .list()
+            .toString()
+        );
+        assertEquals("[]", db.find()
+            .lt("age", 17)
+            .sort()
+            .list()
+            .toString()
+        );
+        assertEquals("[{Helene C 19}]", db.find()
+            .eq("name", "Helene")
+            .lt("age", 23)
+            .sort()
+            .list()
+            .toString()
+        );
+    }
+    
     private static final class Person implements Comparable<Person> {
         
         public final String name;