
name.remal.collections.ObservableCollections Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of common Show documentation
Show all versions of common Show documentation
Java & Kotlin tools: common
The newest version!
package name.remal.collections;
import static java.util.Objects.requireNonNull;
import static name.remal.SneakyThrow.sneakyThrow;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.InvalidObjectException;
import java.io.ObjectInputValidation;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ObservableCollections {
@SuppressFBWarnings({"SE_TRANSIENT_FIELD_NOT_RESTORED", "NFF_NON_FUNCTIONAL_FIELD", "NP_STORE_INTO_NONNULL_FIELD"})
private static abstract class BaseWrappedObservableCollection> implements ObservableCollection, Serializable, ObjectInputValidation {
private static final long serialVersionUID = 1;
@NotNull
protected final C delegate;
protected BaseWrappedObservableCollection(@NotNull C delegate) {
this.delegate = requireNonNull(delegate, "delegate can't be null");
}
/*
* For deserialization
*/
@SuppressWarnings("ConstantConditions")
protected BaseWrappedObservableCollection() {
delegate = null;
}
@SuppressWarnings("ConstantConditions")
@Override
public void validateObject() throws InvalidObjectException {
if (delegate == null) {
throw new InvalidObjectException("delegate can't be null");
}
}
@NotNull
private final transient List> elementAddedHandlers = new ArrayList<>();
@Override
@NotNull
public HandlerRegistration registerElementAddedHandler(@NotNull ElementAddedHandler handler) {
elementAddedHandlers.add(handler);
return () -> elementAddedHandlers.removeIf(it -> it == handler);
}
protected void invokeElementAddedHandlers(@Nullable E element) {
if (element != null) {
try {
for (ElementAddedHandler handler : elementAddedHandlers) {
handler.onElementAdded(element);
}
} catch (Throwable throwable) {
throw sneakyThrow(throwable);
}
}
}
@NotNull
private final transient List> elementRemovedHandlers = new ArrayList<>();
@Override
@NotNull
public HandlerRegistration registerElementRemovedHandler(@NotNull ElementRemovedHandler handler) {
elementRemovedHandlers.add(handler);
return () -> elementRemovedHandlers.removeIf(it -> it == handler);
}
protected void invokeElementRemovedHandlers(@Nullable E element) {
if (element != null) {
try {
for (ElementRemovedHandler handler : elementRemovedHandlers) {
handler.onElementRemoved(element);
}
} catch (Throwable throwable) {
throw sneakyThrow(throwable);
}
}
}
@Override
public boolean add(E e) {
boolean result = delegate.add(e);
if (result) {
invokeElementAddedHandlers(e);
}
return result;
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(Object o) {
boolean result = delegate.remove(o);
if (result) {
invokeElementRemovedHandlers((E) o);
}
return result;
}
@NotNull
@Override
public Iterator iterator() {
return new Iterator() {
private final Iterator delegateIterator = delegate.iterator();
@Nullable
private E lastReturned;
@Override
public boolean hasNext() {
return delegateIterator.hasNext();
}
@Override
public E next() {
return lastReturned = delegateIterator.next();
}
@Override
public void remove() {
delegateIterator.remove();
invokeElementRemovedHandlers(lastReturned);
lastReturned = null;
}
};
}
@Override
public boolean addAll(@NotNull Collection extends E> c) {
boolean result = false;
for (E e : c) {
result |= add(e);
}
return result;
}
@Override
public boolean removeAll(@NotNull Collection> c) {
boolean result = false;
for (Object e : c) {
result |= remove(e);
}
return result;
}
@SuppressWarnings("unchecked")
@Override
public void clear() {
Object[] elements = toArray();
delegate.clear();
for (Object element : elements) {
invokeElementRemovedHandlers((E) element);
}
}
@Override
public boolean retainAll(@NotNull Collection> c) {
boolean result = false;
Iterator iterator = iterator();
while (iterator.hasNext()) {
E element = iterator.next();
if (!c.contains(element)) {
iterator.remove();
result = true;
}
}
return result;
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public boolean contains(Object o) {
return delegate.contains(o);
}
@NotNull
@Override
public Object[] toArray() {
return delegate.toArray();
}
@SuppressWarnings("SuspiciousToArrayCall")
@NotNull
@Override
public T[] toArray(@NotNull T[] a) {
return delegate.toArray(a);
}
@Override
public boolean containsAll(@NotNull Collection> c) {
return delegate.containsAll(c);
}
@Override
public String toString() {
return delegate.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BaseWrappedObservableCollection)) return false;
BaseWrappedObservableCollection, ?> that = (BaseWrappedObservableCollection, ?>) o;
return Objects.equals(delegate, that.delegate);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
}
private static class WrappedObservableCollection extends BaseWrappedObservableCollection> {
private static final long serialVersionUID = 1;
private WrappedObservableCollection(@NotNull Collection delegate) {
super(delegate);
}
/*
* For deserialization
*/
@SuppressWarnings("unused")
private WrappedObservableCollection() {
}
}
@NotNull
public static ObservableCollection observableCollection(@NotNull Collection collection) {
return new WrappedObservableCollection<>(collection);
}
private static class WrappedObservableList extends BaseWrappedObservableCollection> implements ObservableList {
private static final long serialVersionUID = 1;
private WrappedObservableList(@NotNull List delegate) {
super(delegate);
}
/*
* For deserialization
*/
@SuppressWarnings("unused")
private WrappedObservableList() {
}
@Override
public E set(int index, E element) {
E prev = delegate.set(index, element);
if (!Objects.equals(prev, element)) {
invokeElementRemovedHandlers(prev);
invokeElementAddedHandlers(element);
}
return prev;
}
@Override
public void add(int index, E element) {
delegate.add(index, element);
invokeElementAddedHandlers(element);
}
@Override
public boolean addAll(int index, @NotNull Collection extends E> c) {
boolean result = delegate.addAll(index, c);
if (result) {
for (E e : c) {
invokeElementAddedHandlers(e);
}
}
return result;
}
@Override
public E remove(int index) {
E prev = delegate.remove(index);
invokeElementRemovedHandlers(prev);
return prev;
}
@NotNull
@Override
public ListIterator listIterator(int index) {
return new ListIterator() {
private final ListIterator delegateIterator = delegate.listIterator(index);
@Nullable
private E lastReturned;
@Override
public boolean hasNext() {
return delegateIterator.hasNext();
}
@Override
public E next() {
return lastReturned = delegateIterator.next();
}
@Override
public boolean hasPrevious() {
return delegateIterator.hasPrevious();
}
@Override
public E previous() {
return lastReturned = delegateIterator.previous();
}
@Override
public int nextIndex() {
return delegateIterator.nextIndex();
}
@Override
public int previousIndex() {
return delegateIterator.previousIndex();
}
@Override
public void remove() {
delegateIterator.remove();
invokeElementRemovedHandlers(lastReturned);
lastReturned = null;
}
@Override
public void set(E e) {
E prev = get(nextIndex() - 1);
delegateIterator.set(e);
if (!Objects.equals(prev, e)) {
invokeElementRemovedHandlers(prev);
invokeElementAddedHandlers(e);
}
}
@Override
public void add(E e) {
delegateIterator.add(e);
invokeElementAddedHandlers(e);
}
};
}
@NotNull
@Override
public ListIterator listIterator() {
return listIterator(0);
}
@Override
public E get(int index) {
return delegate.get(index);
}
@Override
public int indexOf(Object o) {
return delegate.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return delegate.lastIndexOf(o);
}
@NotNull
@Override
public List subList(int fromIndex, int toIndex) {
return delegate.subList(fromIndex, toIndex);
}
}
@NotNull
public static ObservableList observableList(@NotNull List list) {
return new WrappedObservableList<>(list);
}
private static class WrappedObservableSet extends BaseWrappedObservableCollection> implements ObservableSet {
private static final long serialVersionUID = 1;
private WrappedObservableSet(@NotNull Set delegate) {
super(delegate);
}
/*
* For deserialization
*/
@SuppressWarnings("unused")
private WrappedObservableSet() {
}
}
@NotNull
public static ObservableSet observableSet(@NotNull Set set) {
return new WrappedObservableSet<>(set);
}
@SuppressWarnings("NonSerializableFieldInSerializableClass")
@SuppressFBWarnings({"SE_TRANSIENT_FIELD_NOT_RESTORED", "NFF_NON_FUNCTIONAL_FIELD", "NP_STORE_INTO_NONNULL_FIELD"})
private static class WrappedObservableMap implements ObservableMap, Serializable, ObjectInputValidation {
private static final long serialVersionUID = 1;
@NotNull
private final Map delegate;
private WrappedObservableMap(@NotNull Map delegate) {
this.delegate = requireNonNull(delegate, "delegate can't be null");
}
/*
* For deserialization
*/
@SuppressWarnings({"ConstantConditions", "unused"})
private WrappedObservableMap() {
delegate = null;
}
@SuppressWarnings("ConstantConditions")
@Override
public void validateObject() throws InvalidObjectException {
if (delegate == null) {
throw new InvalidObjectException("delegate can't be null");
}
}
@NotNull
private final transient List> entryAddedHandlers = new ArrayList<>();
@Override
@NotNull
public HandlerRegistration registerEntryAddedHandler(@NotNull EntryAddedHandler handler) {
entryAddedHandlers.add(handler);
return () -> entryAddedHandlers.removeIf(it -> it == handler);
}
private void invokeEntryAddedHandlers(K key, V value) {
try {
for (EntryAddedHandler handler : entryAddedHandlers) {
handler.onEntryAdded(key, value);
}
} catch (Throwable throwable) {
throw sneakyThrow(throwable);
}
}
@NotNull
private transient final List> entryRemovedHandlers = new ArrayList<>();
@Override
@NotNull
public HandlerRegistration registerEntryRemovedHandler(@NotNull EntryRemovedHandler handler) {
entryRemovedHandlers.add(handler);
return () -> entryRemovedHandlers.removeIf(it -> it == handler);
}
private void invokeEntryRemovedHandlers(K key, V value) {
try {
for (EntryRemovedHandler handler : entryRemovedHandlers) {
handler.onEntryRemoved(key, value);
}
} catch (Throwable throwable) {
throw sneakyThrow(throwable);
}
}
@SuppressWarnings("ConstantConditions")
@Nullable
@Override
public V put(K key, V value) {
boolean containsKey = delegate.containsKey(key);
V prev = delegate.put(key, value);
if (!containsKey) {
invokeEntryAddedHandlers(key, value);
} else if (!Objects.equals(prev, value)) {
invokeEntryRemovedHandlers(key, prev);
invokeEntryAddedHandlers(key, value);
}
return prev;
}
@Override
public void putAll(@NotNull Map extends K, ? extends V> m) {
m.forEach(this::put);
}
@SuppressWarnings({"unchecked", "SuspiciousMethodCalls"})
@Override
public V remove(Object key) {
boolean containsKey = delegate.containsKey(key);
V prev = delegate.remove(key);
if (containsKey) {
invokeEntryRemovedHandlers((K) key, prev);
}
return prev;
}
@Override
public void clear() {
List> entries = new ArrayList<>(delegate.entrySet());
delegate.clear();
for (Entry entry : entries) {
invokeEntryRemovedHandlers(entry.getKey(), entry.getValue());
}
}
@NotNull
@Override
public Set keySet() {
return new AbstractSet() {
private final Set delegateKeySet = delegate.keySet();
@SuppressWarnings({"SuspiciousMethodCalls", "unchecked"})
@Override
public boolean remove(Object o) {
boolean contains = delegate.containsKey(o);
V prev = delegate.remove(o);
if (contains) {
invokeEntryRemovedHandlers((K) o, prev);
}
return contains;
}
@NotNull
@Override
public Iterator iterator() {
return new Iterator() {
private final Iterator> delegateIterator = entrySet().iterator();
@Override
public boolean hasNext() {
return delegateIterator.hasNext();
}
@Override
public K next() {
return delegateIterator.next().getKey();
}
@Override
public void remove() {
delegateIterator.remove();
}
};
}
@Override
public void clear() {
WrappedObservableMap.this.clear();
}
@Override
public int size() {
return delegateKeySet.size();
}
@Override
public boolean contains(Object o) {
return delegateKeySet.contains(o);
}
};
}
@NotNull
@Override
public Collection values() {
return new AbstractCollection() {
private final Collection delegateValues = delegate.values();
@Override
public boolean remove(Object o) {
for (Entry entry : delegate.entrySet()) {
if (Objects.equals(o, entry.getValue())) {
WrappedObservableMap.this.remove(entry.getKey());
return true;
}
}
return false;
}
@NotNull
@Override
public Iterator iterator() {
return new Iterator() {
private final Iterator> delegateIterator = entrySet().iterator();
@Override
public boolean hasNext() {
return delegateIterator.hasNext();
}
@Override
public V next() {
return delegateIterator.next().getValue();
}
@Override
public void remove() {
delegateIterator.remove();
}
};
}
@Override
public void clear() {
WrappedObservableMap.this.clear();
}
@Override
public int size() {
return delegateValues.size();
}
@Override
public boolean contains(Object o) {
return delegateValues.contains(o);
}
};
}
@NotNull
@Override
public Set> entrySet() {
return new AbstractSet>() {
private final Set> delegateEntrySet = delegate.entrySet();
@NotNull
@Override
public Iterator> iterator() {
return new Iterator>() {
private final Iterator> delegateIterator = delegateEntrySet.iterator();
@Nullable
private Entry lastReturned;
@Override
public boolean hasNext() {
return delegateIterator.hasNext();
}
@Override
public Entry next() {
return lastReturned = delegateIterator.next();
}
@Override
public void remove() {
delegateIterator.remove();
if (lastReturned != null) {
invokeEntryRemovedHandlers(lastReturned.getKey(), lastReturned.getValue());
}
lastReturned = null;
}
};
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(Object o) {
boolean result = delegateEntrySet.remove(o);
if (result) {
invokeEntryRemovedHandlers(((Entry) o).getKey(), ((Entry) o).getValue());
}
return result;
}
@Override
public void clear() {
WrappedObservableMap.this.clear();
}
@Override
public int size() {
return delegateEntrySet.size();
}
@Override
public boolean contains(Object o) {
return delegateEntrySet.contains(o);
}
};
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return delegate.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return delegate.containsValue(value);
}
@Override
public V get(Object key) {
return delegate.get(key);
}
@Override
public String toString() {
return delegate.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof WrappedObservableMap)) return false;
WrappedObservableMap, ?> that = (WrappedObservableMap, ?>) o;
return Objects.equals(delegate, that.delegate);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
}
@NotNull
public static ObservableMap observableMap(@NotNull Map map) {
return new WrappedObservableMap<>(map);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy