org.aksw.commons.collection.observable.ObservableSetDifference Maven / Gradle / Ivy
package org.aksw.commons.collection.observable;
import java.beans.PropertyChangeListener;
import java.beans.VetoableChangeListener;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import com.google.common.collect.Sets;
public class ObservableSetDifference
extends AbstractSet
implements ObservableSet
{
protected ObservableSet lhs;
protected ObservableSet rhs;
protected Set effectiveSet;
public ObservableSetDifference(ObservableSet lhs, ObservableSet rhs) {
super();
this.lhs = lhs;
this.rhs = rhs;
this.effectiveSet = Sets.difference(lhs, rhs);
}
@Override
public boolean delta(Collection extends T> additions, Collection> removals) {
throw new UnsupportedOperationException();
}
@Override
public Runnable addVetoableChangeListener(VetoableChangeListener listener) {
Runnable a = lhs.addVetoableChangeListener(convertVetoableChangeListener(this, rhs, listener));
Runnable b = rhs.addVetoableChangeListener(convertVetoableChangeListener(this, lhs, listener));
// Return a runnable that deregister both listeners
return () -> { a.run(); b.run(); };
}
@Override
public Registration addPropertyChangeListener(PropertyChangeListener listener) {
/*
Runnable a = lhs.addPropertyChangeListener(convertPropertyChangeListener(this, rhs, listener));
Runnable b = rhs.addPropertyChangeListener(convertPropertyChangeListener(this, lhs, listener));
// Return a runnable that deregister both listeners
return () -> { a.run(); b.run(); };
*/
Registration a = lhs.addPropertyChangeListener(convertPropertyChangeListener(this, rhs, listener));
Registration b = rhs.addPropertyChangeListener(convertPropertyChangeListener(this, lhs, listener));
// Return a runnable that deregister both listeners
// return () -> { a.run(); b.run(); };
return Registration.from(
() -> { listener.propertyChange(new CollectionChangedEventImpl(
this, this, this,
Collections.emptySet(), Collections.emptySet(), Collections.emptySet())); },
() -> { a.remove(); b.remove(); }
);
}
@SuppressWarnings("unchecked")
public static VetoableChangeListener convertVetoableChangeListener(
Object self, Set other,
VetoableChangeListener listener) {
return ev -> {
CollectionChangedEvent newEv = convertEvent(self, (CollectionChangedEvent)ev, other);
if (newEv.hasChanges()) {
listener.vetoableChange(newEv);
}
};
}
@SuppressWarnings("unchecked")
public static PropertyChangeListener convertPropertyChangeListener(
Object self, Set other,
PropertyChangeListener listener) {
return ev -> {
CollectionChangedEvent newEv = convertEvent(self, (CollectionChangedEvent)ev, other);
if (newEv.hasChanges()) {
listener.propertyChange(newEv);
}
};
}
protected static Set nullSafeDifference(Set set, Set other) {
return set == null ? Collections.emptySet() : Sets.difference((Set)set, other);
}
// @SuppressWarnings("unchecked")
// public static CollectionChangedEventImpl convertVetoableChangeEvent(Object self,
// CollectionChangedEventImpl ev, Set other) {
//
// // Added items that already exist in the 'other' set are substracted
// Set effectiveAdditions = nullSafeDifference((Set)ev.getAdditions(), other);
// // Deletions that already exist in the other set are also substracted
// Set effectiveDeletions = nullSafeDifference((Set)ev.getDeletions(), other);
//
// return new CollectionChangedEventImpl(
// self, self,
// Sets.union(Sets.difference((Set)self, effectiveDeletions), effectiveAdditions),
// effectiveAdditions,
// effectiveDeletions,
// // Refreshes are just passed through
// nullSafeDifference((Set)ev.getRefreshes(), other));
// }
@SuppressWarnings("unchecked")
public static CollectionChangedEvent convertEvent(Object self,
CollectionChangedEvent ev, Set other) {
// Added items that already exist in the 'other' set are substracted
Set effectiveAdditions = nullSafeDifference((Set)ev.getAdditions(), other);
// Deletions that already exist in the other set are also substracted
Set effectiveDeletions = nullSafeDifference((Set)ev.getDeletions(), other);
return new CollectionChangedEventImpl(
self, self,
Sets.union(Sets.difference((Set)self, effectiveDeletions), effectiveAdditions),
effectiveAdditions,
effectiveDeletions,
// Refreshes are just passed through
nullSafeDifference((Set)ev.getRefreshes(), other));
}
@Override
public Iterator iterator() {
return effectiveSet.iterator();
}
@Override
public int size() {
return effectiveSet.size();
}
public static ObservableSet create(ObservableSet a, ObservableSet b) {
return new ObservableSetDifference<>(a, b);
}
public static void main(String[] args) {
ObservableSet a = ObservableSetImpl.decorate(new LinkedHashSet<>());
ObservableSet b = ObservableSetImpl.decorate(new LinkedHashSet<>());
ObservableSet c = ObservableSetDifference.create(a, b);
c.addPropertyChangeListener(ev -> System.out.println(ev));
a.add("Hello"); // expect addition
b.add("Hello"); // expect no event
a.remove("Hello"); // expect no event
b.remove("Hello"); // expect event
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy