소스 검색

#91
new: ObservableGenericMap
new: ObservablePrototypeMap
new: ObservableSet

Ranides Atterwim 3 년 전
부모
커밋
c7d828b413

+ 22 - 11
assira.commons/src/main/java/net/ranides/assira/observable/ObservableCollection.java

@@ -1,23 +1,34 @@
 package net.ranides.assira.observable;
 
-import lombok.RequiredArgsConstructor;
 import net.ranides.assira.collection.ACollection;
-import net.ranides.assira.events.Event;
 import net.ranides.assira.events.EventListener;
+import net.ranides.assira.events.EventRouter;
 
 import java.util.Collection;
 import java.util.Iterator;
 
-@RequiredArgsConstructor
-class ObservableCollection<T> extends ACollection<T> {
+public class ObservableCollection<T> extends ACollection<T> {
+
+    private final EventRouter router;
 
     private final Collection<T> collection;
 
-    private final EventListener<Event> listener;
+    public ObservableCollection(EventRouter router, Collection<T> collection) {
+        this.collection = collection;
+        this.router = router;
+    }
+
+    public EventRouter router() {
+        return router;
+    }
+
+    public <E extends CollectionEvent<T>> void addEventListener(Class<E> event, EventListener<? super E> listener) {
+        router.addEventListener(event, listener);
+    }
 
     @Override
     public Iterator<T> iterator() {
-        return new ObservableIterator<>(collection, collection.iterator(), listener);
+        return new ObservableIterator<>(router, collection, collection.iterator());
     }
 
     @Override
@@ -28,7 +39,7 @@ class ObservableCollection<T> extends ACollection<T> {
     @Override
     public boolean add(T t) {
         if (collection.add(t)) {
-            listener.handleEvent(new CollectionEvent.Add<>(collection, t));
+            router.signalEvent(new CollectionEvent.Add<>(collection, t));
             return true;
         }
         return false;
@@ -37,7 +48,7 @@ class ObservableCollection<T> extends ACollection<T> {
     @Override
     public boolean remove(Object o) {
         if (collection.remove(o)) {
-            listener.handleEvent(new CollectionEvent.Remove<>(collection, (T) o));
+            router.signalEvent(new CollectionEvent.Remove<>(collection, (T) o));
             return true;
         }
         return false;
@@ -46,7 +57,7 @@ class ObservableCollection<T> extends ACollection<T> {
     @Override
     public boolean addAll(Collection<? extends T> c) {
         if (collection.addAll(c)) {
-            listener.handleEvent(new CollectionEvent.AddMany<>(collection, c));
+            router.signalEvent(new CollectionEvent.AddMany<>(collection, c));
             return true;
         }
         return false;
@@ -55,7 +66,7 @@ class ObservableCollection<T> extends ACollection<T> {
     @Override
     public boolean removeAll(Collection<?> c) {
         if (collection.removeAll(c)) {
-            listener.handleEvent(new CollectionEvent.RemoveMany<>(collection, (Collection<T>) c));
+            router.signalEvent(new CollectionEvent.RemoveMany<>(collection, (Collection<T>) c));
             return true;
         }
         return false;
@@ -66,7 +77,7 @@ class ObservableCollection<T> extends ACollection<T> {
         boolean empty = collection.isEmpty();
         collection.clear();
         if (!empty) {
-            listener.handleEvent(new CollectionEvent.Clear<>(collection));
+            router.signalEvent(new CollectionEvent.Clear<>(collection));
         }
     }
 }

+ 0 - 21
assira.commons/src/main/java/net/ranides/assira/observable/ObservableCollections.java

@@ -1,21 +0,0 @@
-package net.ranides.assira.observable;
-
-import lombok.experimental.UtilityClass;
-import net.ranides.assira.collection.prototype.GenericMap;
-import net.ranides.assira.collection.prototype.PrototypeMap;
-import net.ranides.assira.events.EventListener;
-
-@UtilityClass
-public class ObservableCollections {
-
-    // TODO
-    public static PrototypeMap observable(PrototypeMap map, EventListener<?> listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    // TODO
-    public static <K> GenericMap<K> observable(GenericMap<K> map, EventListener<?> listener) {
-        throw new UnsupportedOperationException();
-    }
-
-}

+ 22 - 0
assira.commons/src/main/java/net/ranides/assira/observable/ObservableGenericMap.java

@@ -0,0 +1,22 @@
+package net.ranides.assira.observable;
+
+import net.ranides.assira.collection.maps.OpenMultiMap;
+import net.ranides.assira.collection.prototype.OpenGenericMap;
+import net.ranides.assira.collection.utils.HashCollection;
+import net.ranides.assira.events.EventRouter;
+
+public class ObservableGenericMap<K> extends OpenGenericMap<K> {
+
+    public ObservableGenericMap(EventRouter router) {
+        this(router, HashCollection.INITIAL_SIZE, HashCollection.LOAD_FACTOR);
+    }
+
+    public ObservableGenericMap(EventRouter router, int capacity) {
+        this(router, capacity, HashCollection.LOAD_FACTOR);
+    }
+
+    public ObservableGenericMap(EventRouter router, int capacity, float factor) {
+        super(new ObservableMap<>(router, new OpenMultiMap<>(capacity, factor)));
+    }
+
+}

+ 10 - 6
assira.commons/src/main/java/net/ranides/assira/observable/ObservableIterator.java

@@ -1,18 +1,22 @@
 package net.ranides.assira.observable;
 
 import lombok.RequiredArgsConstructor;
-import net.ranides.assira.events.Event;
-import net.ranides.assira.events.EventListener;
+import net.ranides.assira.events.EventRouter;
 
 import java.util.Collection;
 import java.util.Iterator;
 
-@RequiredArgsConstructor
 class ObservableIterator<T> implements Iterator<T> {
-    private T last;
+    private final EventRouter router;
     private final Collection<T> source;
     private final Iterator<T> itr;
-    private final EventListener<Event> listener;
+    private T last;
+
+    public ObservableIterator(EventRouter router, Collection<T> source, Iterator<T> itr) {
+        this.router = router;
+        this.source = source;
+        this.itr = itr;
+    }
 
     @Override
     public boolean hasNext() {
@@ -27,6 +31,6 @@ class ObservableIterator<T> implements Iterator<T> {
     @Override
     public void remove() {
         itr.remove();
-        listener.handleEvent(new CollectionEvent.Remove<>(source, last));
+        router.signalEvent(new CollectionEvent.Remove<>(source, last));
     }
 }

+ 4 - 5
assira.commons/src/main/java/net/ranides/assira/observable/ObservableList.java

@@ -1,7 +1,6 @@
 package net.ranides.assira.observable;
 
 import lombok.RequiredArgsConstructor;
-import net.ranides.assira.events.Event;
 import net.ranides.assira.events.EventListener;
 import net.ranides.assira.events.EventRouter;
 
@@ -18,7 +17,7 @@ class ObservableList<T> extends AbstractList<T> {
         return router;
     }
 
-    public <T extends Event> void addEventListener(Class<T> event, EventListener<? super T> listener) {
+    public <E extends ListEvent<T>> void addEventListener(Class<E> event, EventListener<? super E> listener) {
         router.addEventListener(event, listener);
     }
 
@@ -74,17 +73,17 @@ class ObservableList<T> extends AbstractList<T> {
 
     @Override
     public Iterator<T> iterator() {
-        return new ObservableListIterator<>(list, list.listIterator(), router);
+        return new ObservableListIterator<>(router, list, list.listIterator());
     }
 
     @Override
     public ListIterator<T> listIterator() {
-        return new ObservableListIterator<>(list, list.listIterator(), router);
+        return new ObservableListIterator<>(router, list, list.listIterator());
     }
 
     @Override
     public ListIterator<T> listIterator(int index) {
-        return new ObservableListIterator<>(list, list.listIterator(index), router);
+        return new ObservableListIterator<>(router, list, list.listIterator(index));
     }
 
     @Override

+ 12 - 9
assira.commons/src/main/java/net/ranides/assira/observable/ObservableListIterator.java

@@ -1,18 +1,21 @@
 package net.ranides.assira.observable;
 
-import lombok.RequiredArgsConstructor;
-import net.ranides.assira.events.Event;
-import net.ranides.assira.events.EventListener;
+import net.ranides.assira.events.EventRouter;
 
 import java.util.List;
 import java.util.ListIterator;
 
-@RequiredArgsConstructor
 class ObservableListIterator<T> implements ListIterator<T> {
-    private T last;
+    private final EventRouter router;
     private final List<T> source;
     private final ListIterator<T> itr;
-    private final EventListener<Event> listener;
+    private T last;
+
+    public ObservableListIterator(EventRouter router, List<T> source, ListIterator<T> itr) {
+        this.source = source;
+        this.itr = itr;
+        this.router = router;
+    }
 
     @Override
     public boolean hasNext() {
@@ -47,18 +50,18 @@ class ObservableListIterator<T> implements ListIterator<T> {
     @Override
     public void set(T t) {
         itr.set(t);
-        listener.handleEvent(new ListEvent.Set<>(source, last, t));
+        router.signalEvent(new ListEvent.Set<>(source, last, t));
     }
 
     @Override
     public void add(T t) {
         itr.add(t);
-        listener.handleEvent(new ListEvent.Add<>(source, t));
+        router.signalEvent(new ListEvent.Add<>(source, t));
     }
 
     @Override
     public void remove() {
         itr.remove();
-        listener.handleEvent(new ListEvent.Remove<>(source, last));
+        router.signalEvent(new ListEvent.Remove<>(source, last));
     }
 }

+ 26 - 9
assira.commons/src/main/java/net/ranides/assira/observable/ObservableMap.java

@@ -1,21 +1,38 @@
 package net.ranides.assira.observable;
 
-import lombok.RequiredArgsConstructor;
 import net.ranides.assira.collection.maps.AMap;
-import net.ranides.assira.events.Event;
 import net.ranides.assira.events.EventListener;
+import net.ranides.assira.events.EventRouter;
 
 import java.util.AbstractSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Supplier;
 
-@RequiredArgsConstructor
 public class ObservableMap<K,V> extends AMap<K,V> {
 
     private final Map<K,V> map;
 
-    private final EventListener<Event> listener;
+    private final EventRouter router;
+
+    public ObservableMap(EventRouter router, Map<K, V> map) {
+        this.map = map;
+        this.router = router;
+    }
+
+    public ObservableMap(EventRouter router, Supplier<Map<K,V>> that, Map<K, V> map) {
+        this.map = map;
+        this.router = router;
+    }
+
+    public EventRouter router() {
+        return router;
+    }
+
+    public <E extends MapEvent<K,V>> void addEventListener(Class<E> event, EventListener<? super E> listener) {
+        router.addEventListener(event, listener);
+    }
 
     @Override
     public int size() {
@@ -45,7 +62,7 @@ public class ObservableMap<K,V> extends AMap<K,V> {
     @Override
     public V put(K key, V value) {
         V prev = map.put(key, value);
-        listener.handleEvent(new MapEvent.Put<>(map, key, prev, value));
+        router.signalEvent(new MapEvent.Put<>(map, key, prev, value));
         return prev;
     }
 
@@ -53,7 +70,7 @@ public class ObservableMap<K,V> extends AMap<K,V> {
     public V remove(Object key) {
         V prev = map.remove(key);
         if(prev != null) {
-            listener.handleEvent(new MapEvent.Remove<>(map, (K)key, prev));
+            router.signalEvent(new MapEvent.Remove<>(map, (K)key, prev));
         }
         return prev;
     }
@@ -61,13 +78,13 @@ public class ObservableMap<K,V> extends AMap<K,V> {
     @Override
     public void putAll(Map<? extends K, ? extends V> m) {
         map.putAll(m);
-        listener.handleEvent(new MapEvent.PutAll<>(map, m));
+        router.signalEvent(new MapEvent.PutAll<>(map, m));
     }
 
     @Override
     public void clear() {
         map.clear();
-        listener.handleEvent(new MapEvent.Clear<>(map));
+        router.signalEvent(new MapEvent.Clear<>(map));
     }
 
     @Override
@@ -76,7 +93,7 @@ public class ObservableMap<K,V> extends AMap<K,V> {
             @Override
             public Iterator<Entry<K, V>> iterator() {
                 Set<Entry<K, V>> entries = map.entrySet();
-                return new ObservableIterator<>(entries, entries.iterator(), listener);
+                return new ObservableIterator<>(router, entries, entries.iterator());
             }
 
             @Override

+ 44 - 0
assira.commons/src/main/java/net/ranides/assira/observable/ObservablePrototypeMap.java

@@ -0,0 +1,44 @@
+package net.ranides.assira.observable;
+
+import net.ranides.assira.collection.maps.OpenMap;
+import net.ranides.assira.collection.prototype.PrototypeMap;
+import net.ranides.assira.events.EventListener;
+import net.ranides.assira.events.EventRouter;
+
+import java.util.Map;
+
+public class ObservablePrototypeMap extends PrototypeMap {
+
+    private final EventRouter router;
+
+    public ObservablePrototypeMap(EventRouter router) {
+        this(true, router, null, new OpenMap<>());
+    }
+
+    public ObservablePrototypeMap(EventRouter router, PrototypeMap parent) {
+        this(true, router, parent, new OpenMap<>());
+    }
+
+    public ObservablePrototypeMap(EventRouter router, Map<Object, ?> content) {
+        this(true, router, null, new OpenMap<>(content));
+    }
+
+    public ObservablePrototypeMap(EventRouter router, PrototypeMap parent, Map<Object, ?> content) {
+        this(true, router, parent, new OpenMap<>(content));
+    }
+
+    private ObservablePrototypeMap(boolean direct, EventRouter router, PrototypeMap parent, Map<Object, Object> content) {
+        // todo: our router emits wrong "source" (to internal map instead of this map)
+        super(direct, parent, new ObservableMap<>(router, content));
+        this.router = router;
+    }
+
+    public EventRouter router() {
+        return router;
+    }
+
+    public <E extends MapEvent<Object, Object>> void addEventListener(Class<E> event, EventListener<? super E> listener) {
+        router.addEventListener(event, listener);
+    }
+
+}

+ 84 - 0
assira.commons/src/main/java/net/ranides/assira/observable/ObservableSet.java

@@ -0,0 +1,84 @@
+package net.ranides.assira.observable;
+
+import net.ranides.assira.collection.sets.ASet;
+import net.ranides.assira.events.EventListener;
+import net.ranides.assira.events.EventRouter;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+class ObservableSet<T> extends ASet<T> {
+
+    private final EventRouter router;
+
+    private final Set<T> collection;
+
+    public ObservableSet(EventRouter router, Set<T> collection) {
+        this.collection = collection;
+        this.router = router;
+    }
+
+    public EventRouter router() {
+        return router;
+    }
+
+    public <E extends CollectionEvent<T>> void addEventListener(Class<E> event, EventListener<? super E> listener) {
+        router.addEventListener(event, listener);
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+        return new ObservableIterator<>(router, collection, collection.iterator());
+    }
+
+    @Override
+    public int size() {
+        return collection.size();
+    }
+
+    @Override
+    public boolean add(T t) {
+        if (collection.add(t)) {
+            router.signalEvent(new CollectionEvent.Add<>(collection, t));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        if (collection.remove(o)) {
+            router.signalEvent(new CollectionEvent.Remove<>(collection, (T) o));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends T> c) {
+        if (collection.addAll(c)) {
+            router.signalEvent(new CollectionEvent.AddMany<>(collection, c));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        if (collection.removeAll(c)) {
+            router.signalEvent(new CollectionEvent.RemoveMany<>(collection, (Collection<T>) c));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void clear() {
+        boolean empty = collection.isEmpty();
+        collection.clear();
+        if (!empty) {
+            router.signalEvent(new CollectionEvent.Clear<>(collection));
+        }
+    }
+}

+ 6 - 1
assira.core/src/main/java/net/ranides/assira/collection/prototype/OpenGenericMap.java

@@ -12,6 +12,7 @@ import java.util.Map.Entry;
 import net.ranides.assira.collection.maps.OpenMultiMap;
 import net.ranides.assira.collection.sets.SetUtils;
 import net.ranides.assira.collection.utils.HashCollection;
+import net.ranides.assira.events.EventRouter;
 import net.ranides.assira.reflection.IClass;
 import net.ranides.assira.reflection.util.ClassUtils;
 
@@ -48,7 +49,11 @@ public class OpenGenericMap<K> implements GenericMap<K> {
      * @param factor factor
      */
     public OpenGenericMap(int capacity, float factor) {
-        this.map = new OpenMultiMap<>(capacity, factor);
+        this(new OpenMultiMap<>(capacity, factor));
+    }
+
+    protected OpenGenericMap(Map<GenericKey<K,?>, Object> map) {
+        this.map = map;
     }
 
     /**

+ 6 - 0
assira.core/src/main/java/net/ranides/assira/collection/prototype/PrototypeMap.java

@@ -76,6 +76,12 @@ public class PrototypeMap extends AMap<Object, Object> implements Map<Object, Ob
         this.declared = Collections.emptyMap();
     }
 
+    protected PrototypeMap(boolean direct, PrototypeMap parent, Map<Object, Object> content) {
+        assert direct : "this is constructor for direct map";
+        this.parent = parent;
+        this.declared = content;
+    }
+
     /**
      * Returns prototype, or null
      *