Explorar o código

#91 collection, list, map

Ranides Atterwim %!s(int64=3) %!d(string=hai) anos
pai
achega
880658b2d3

+ 101 - 0
assira.commons/src/main/java/net/ranides/assira/observable/CollectionEvent.java

@@ -0,0 +1,101 @@
+package net.ranides.assira.observable;
+
+import lombok.RequiredArgsConstructor;
+import net.ranides.assira.events.Event;
+
+import java.util.Collection;
+
+public interface CollectionEvent<T> extends Event {
+
+    Collection<T> collection();
+
+    @RequiredArgsConstructor
+    class Remove<T> implements CollectionEvent<T> {
+        private final Collection<T> collection;
+        private final T value;
+
+        @Override
+        public Collection<T> collection() {
+            return collection;
+        }
+
+        public T value() {
+            return value;
+        }
+    }
+
+    @RequiredArgsConstructor
+    class RemoveMany<T> implements CollectionEvent<T> {
+        private final Collection<T> collection;
+        private final Collection<T> values;
+
+        @Override
+        public Collection<T> collection() {
+            return collection;
+        }
+
+        public Collection<T> values() {
+            return values;
+        }
+    }
+
+    @RequiredArgsConstructor
+    class Clear<T> implements CollectionEvent<T> {
+        private final Collection<T> collection;
+
+        @Override
+        public Collection<T> collection() {
+            return collection;
+        }
+    }
+
+    @RequiredArgsConstructor
+    class Set<T> implements CollectionEvent<T> {
+        private final Collection<T> collection;
+        private final T previous;
+        private final T value;
+
+        @Override
+        public Collection<T> collection() {
+            return collection;
+        }
+
+        public T previous() {
+            return previous;
+        }
+
+        public T value() {
+            return value;
+        }
+    }
+
+    @RequiredArgsConstructor
+    class Add<T> implements CollectionEvent<T> {
+        private final Collection<T> collection;
+        private final T value;
+
+        @Override
+        public Collection<T> collection() {
+            return collection;
+        }
+
+        public T value() {
+            return value;
+        }
+    }
+
+    @RequiredArgsConstructor
+    class AddMany<T> implements CollectionEvent<T> {
+        private final Collection<T> collection;
+        private final Collection<? extends T> values;
+
+        @Override
+        public Collection<T> collection() {
+            return collection;
+        }
+
+        public Collection<? extends T> values() {
+            return values;
+        }
+    }
+}

+ 47 - 0
assira.commons/src/main/java/net/ranides/assira/observable/ListEvent.java

@@ -0,0 +1,47 @@
+package net.ranides.assira.observable;
+
+import java.util.Collection;
+import java.util.List;
+
+public interface ListEvent<T> extends CollectionEvent<T> {
+
+    default List<T> list() {
+        return (List<T>) collection();
+    }
+
+    class Remove<T> extends CollectionEvent.Remove<T> implements ListEvent<T> {
+        protected Remove(List<T> list, T value) {
+            super(list, value);
+        }
+    }
+
+    class RemoveMany<T> extends CollectionEvent.RemoveMany<T> implements ListEvent<T> {
+        protected RemoveMany(List<T> list, Collection<T> values) {
+            super(list, values);
+        }
+    }
+
+    class Clear<T> extends CollectionEvent.Clear<T> implements ListEvent<T> {
+        protected Clear(List<T> list) {
+            super(list);
+        }
+    }
+
+    class Set<T> extends CollectionEvent.Set<T> implements ListEvent<T> {
+        protected Set(List<T> list, T previous, T value) {
+            super(list, previous, value);
+        }
+    }
+
+    class Add<T> extends CollectionEvent.Add<T> implements ListEvent<T> {
+        protected Add(List<T> list, T value) {
+            super(list, value);
+        }
+    }
+
+    class AddMany<T> extends CollectionEvent.AddMany<T> implements ListEvent<T> {
+        protected AddMany(List<T> list, Collection<? extends T> values) {
+            super(list, values);
+        }
+    }
+}

+ 77 - 0
assira.commons/src/main/java/net/ranides/assira/observable/MapEvent.java

@@ -0,0 +1,77 @@
+package net.ranides.assira.observable;
+
+import lombok.RequiredArgsConstructor;
+import net.ranides.assira.events.Event;
+
+import java.util.Map;
+
+public interface MapEvent<K,V> extends Event {
+
+    Map<K,V> map();
+
+    @RequiredArgsConstructor
+    class Remove<K,V> implements MapEvent<K,V> {
+        private final Map<K,V> map;
+        private final K key;
+        private final V value;
+
+        public Map<K, V> map() {
+            return map;
+        }
+
+        public K key() {
+            return key;
+        }
+
+        public V value() {
+            return value;
+        }
+    }
+
+    @RequiredArgsConstructor
+    class Clear<K,V> implements MapEvent<K,V> {
+        private final Map<K,V> map;
+
+        public Map<K, V> map() {
+            return map;
+        }
+    }
+
+    @RequiredArgsConstructor
+    class Put<K,V> implements MapEvent<K,V> {
+        private final Map<K,V> map;
+        private final K key;
+        private final V previous;
+        private final V value;
+
+        public Map<K, V> map() {
+            return map;
+        }
+
+        public K key() {
+            return key;
+        }
+
+        public V previous() {
+            return previous;
+        }
+
+        public V value() {
+            return value;
+        }
+    }
+
+    @RequiredArgsConstructor
+    class PutAll<K,V> implements MapEvent<K,V> {
+        private final Map<K,V> map;
+        private final Map<? extends K,? extends V> values;
+
+        public Map<K, V> map() {
+            return map;
+        }
+
+        public Map<? extends K,? extends V> values() {
+            return values;
+        }
+    }
+}

+ 72 - 0
assira.commons/src/main/java/net/ranides/assira/observable/ObservableCollection.java

@@ -0,0 +1,72 @@
+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 java.util.Collection;
+import java.util.Iterator;
+
+@RequiredArgsConstructor
+class ObservableCollection<T> extends ACollection<T> {
+
+    private final Collection<T> collection;
+
+    private final EventListener<Event> listener;
+
+    @Override
+    public Iterator<T> iterator() {
+        return new ObservableIterator<>(collection, collection.iterator(), listener);
+    }
+
+    @Override
+    public int size() {
+        return collection.size();
+    }
+
+    @Override
+    public boolean add(T t) {
+        if (collection.add(t)) {
+            listener.handleEvent(new CollectionEvent.Add<>(collection, t));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        if (collection.remove(o)) {
+            listener.handleEvent(new CollectionEvent.Remove<>(collection, (T) o));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends T> c) {
+        if (collection.addAll(c)) {
+            listener.handleEvent(new CollectionEvent.AddMany<>(collection, c));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        if (collection.removeAll(c)) {
+            listener.handleEvent(new CollectionEvent.RemoveMany<>(collection, (Collection<T>) c));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void clear() {
+        boolean empty = collection.isEmpty();
+        collection.clear();
+        if (!empty) {
+            listener.handleEvent(new CollectionEvent.Clear<>(collection));
+        }
+    }
+}

+ 32 - 0
assira.commons/src/main/java/net/ranides/assira/observable/ObservableIterator.java

@@ -0,0 +1,32 @@
+package net.ranides.assira.observable;
+
+import lombok.RequiredArgsConstructor;
+import net.ranides.assira.events.Event;
+import net.ranides.assira.events.EventListener;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+@RequiredArgsConstructor
+class ObservableIterator<T> implements Iterator<T> {
+    private T last;
+    private final Collection<T> source;
+    private final Iterator<T> itr;
+    private final EventListener<Event> listener;
+
+    @Override
+    public boolean hasNext() {
+        return itr.hasNext();
+    }
+
+    @Override
+    public T next() {
+        return last = itr.next();
+    }
+
+    @Override
+    public void remove() {
+        itr.remove();
+        listener.handleEvent(new CollectionEvent.Remove<>(source, last));
+    }
+}

+ 107 - 0
assira.commons/src/main/java/net/ranides/assira/observable/ObservableList.java

@@ -0,0 +1,107 @@
+package net.ranides.assira.observable;
+
+import lombok.RequiredArgsConstructor;
+import net.ranides.assira.events.Event;
+import net.ranides.assira.events.EventListener;
+
+import java.util.*;
+
+@RequiredArgsConstructor
+class ObservableList<T> extends AbstractList<T> {
+
+    private final List<T> list;
+
+    private final EventListener<Event> listener;
+
+    @Override
+    public T get(int index) {
+        return list.get(index);
+    }
+
+    @Override
+    public int size() {
+        return list.size();
+    }
+
+    @Override
+    public boolean add(T t) {
+        list.add(t);
+        listener.handleEvent(new ListEvent.Add<>(list, t));
+        return true;
+    }
+
+    @Override
+    public T set(int index, T element) {
+        T prev = list.set(index, element);
+        listener.handleEvent(new ListEvent.Set<>(list, prev, element));
+        return prev;
+    }
+
+    @Override
+    public void add(int index, T element) {
+        list.add(index, element);
+        listener.handleEvent(new ListEvent.Add<>(list, element));
+    }
+
+    @Override
+    public T remove(int index) {
+        T prev = list.remove(index);
+        listener.handleEvent(new ListEvent.Remove<>(list, prev));
+        return prev;
+    }
+
+    @Override
+    public void clear() {
+        list.clear();
+        listener.handleEvent(new ListEvent.Clear<>(list));
+    }
+
+    @Override
+    public boolean addAll(int index, Collection<? extends T> c) {
+        list.addAll(index, c);
+        listener.handleEvent(new ListEvent.AddMany<>(list, c));
+        return true;
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+        return new ObservableListIterator<>(list, list.listIterator(), listener);
+    }
+
+    @Override
+    public ListIterator<T> listIterator() {
+        return new ObservableListIterator<>(list, list.listIterator(), listener);
+    }
+
+    @Override
+    public ListIterator<T> listIterator(int index) {
+        return new ObservableListIterator<>(list, list.listIterator(index), listener);
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        if (list.remove(o)) {
+            listener.handleEvent(new ListEvent.Remove<>(list, (T) o));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends T> c) {
+        if (list.addAll(c)) {
+            listener.handleEvent(new ListEvent.AddMany<>(list, c));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        if (list.removeAll(c)) {
+            listener.handleEvent(new ListEvent.Clear<>(list));
+            return true;
+        }
+        return false;
+    }
+}

+ 64 - 0
assira.commons/src/main/java/net/ranides/assira/observable/ObservableListIterator.java

@@ -0,0 +1,64 @@
+package net.ranides.assira.observable;
+
+import lombok.RequiredArgsConstructor;
+import net.ranides.assira.events.Event;
+import net.ranides.assira.events.EventListener;
+
+import java.util.List;
+import java.util.ListIterator;
+
+@RequiredArgsConstructor
+class ObservableListIterator<T> implements ListIterator<T> {
+    private T last;
+    private final List<T> source;
+    private final ListIterator<T> itr;
+    private final EventListener<Event> listener;
+
+    @Override
+    public boolean hasNext() {
+        return itr.hasNext();
+    }
+
+    @Override
+    public T next() {
+        return last = itr.next();
+    }
+
+    @Override
+    public boolean hasPrevious() {
+        return itr.hasPrevious();
+    }
+
+    @Override
+    public T previous() {
+        return last = itr.previous();
+    }
+
+    @Override
+    public int nextIndex() {
+        return itr.nextIndex();
+    }
+
+    @Override
+    public int previousIndex() {
+        return itr.previousIndex();
+    }
+
+    @Override
+    public void set(T t) {
+        itr.set(t);
+        listener.handleEvent(new ListEvent.Set<>(source, last, t));
+    }
+
+    @Override
+    public void add(T t) {
+        itr.add(t);
+        listener.handleEvent(new ListEvent.Add<>(source, t));
+    }
+
+    @Override
+    public void remove() {
+        itr.remove();
+        listener.handleEvent(new ListEvent.Remove<>(source, last));
+    }
+}

+ 102 - 0
assira.commons/src/main/java/net/ranides/assira/observable/ObservableMap.java

@@ -0,0 +1,102 @@
+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 java.util.AbstractSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+@RequiredArgsConstructor
+public class ObservableMap<K,V> extends AMap<K,V> {
+
+    private final Map<K,V> map;
+
+    private final EventListener<Event> listener;
+
+    @Override
+    public int size() {
+        return map.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return map.isEmpty();
+    }
+
+    @Override
+    public boolean containsKey(Object key) {
+        return map.containsKey(key);
+    }
+
+    @Override
+    public boolean containsValue(Object value) {
+        return map.containsValue(value);
+    }
+
+    @Override
+    public V get(Object key) {
+        return map.get(key);
+    }
+
+    @Override
+    public V put(K key, V value) {
+        V prev = map.put(key, value);
+        listener.handleEvent(new MapEvent.Put<>(map, key, prev, value));
+        return prev;
+    }
+
+    @Override
+    public V remove(Object key) {
+        V prev = map.remove(key);
+        if(prev != null) {
+            listener.handleEvent(new MapEvent.Remove<>(map, (K)key, prev));
+        }
+        return prev;
+    }
+
+    @Override
+    public void putAll(Map<? extends K, ? extends V> m) {
+        map.putAll(m);
+        listener.handleEvent(new MapEvent.PutAll<>(map, m));
+    }
+
+    @Override
+    public void clear() {
+        map.clear();
+        listener.handleEvent(new MapEvent.Clear<>(map));
+    }
+
+    @Override
+    public Set<Entry<K, V>> entrySet() {
+        return new AbstractSet<Entry<K, V>>() {
+            @Override
+            public Iterator<Entry<K, V>> iterator() {
+                Set<Entry<K, V>> entries = map.entrySet();
+                return new ObservableIterator<>(entries, entries.iterator(), listener);
+            }
+
+            @Override
+            public int size() {
+                return map.size();
+            }
+
+            @Override
+            public boolean remove(Object object) {
+                if (object instanceof Map.Entry) {
+                    Map.Entry<?, ?> entry = (Map.Entry<?,?>) object;
+                    return ObservableMap.this.remove(entry.getKey(), entry.getValue());
+                }
+                return false;
+            }
+
+            @Override
+            public void clear() {
+                ObservableMap.this.clear();
+            }
+        };
+    }
+}