All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aksw.commons.collection.observable.ObservableSetDifference Maven / Gradle / Ivy

There is a newer version: 0.9.9
Show newest version
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 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