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

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

There is a newer version: 0.9.9
Show newest version
package org.aksw.commons.collection.observable;

import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeSupport;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;

import com.google.common.collect.Sets;

public class ObservableCollectionOps {


    /**
     * Updates the 'backend' collection by first performing removals followed by additions.
     *
     * @param 
     * @param self
     * @param backend
     * @param vcs
     * @param pcs
     * @param clearIntersection Whether to adept additions and removals for an empty intersection
     * @param rawAdditions
     * @param rawRemovals
     * @return
     */
    public static  boolean applyDeltaSet(
            Collection self,
            Set backend,
            VetoableChangeSupport vcs,
            PropertyChangeSupport pcs,
            boolean clearIntersection,
            Collection rawAdditions, Collection rawRemovals) {

        // Set up the physical removals / additions that will be sent to the backend
        // This may include overlapping items
        @SuppressWarnings("unchecked")
        Set physRemovals = rawRemovals == self
            ? rawRemovals.stream().map(x -> (T)x).collect(Collectors.toCollection(LinkedHashSet::new))
            : rawRemovals.stream().filter(backend::contains).map(x -> (T)x).collect(Collectors.toCollection(LinkedHashSet::new));

        Set physAdditions = rawAdditions.stream()
                .filter(x -> !backend.contains(x) || physRemovals.contains(x))
                .collect(Collectors.toCollection(LinkedHashSet::new));

        Set intersection = new LinkedHashSet<>(Sets.intersection(physAdditions, physRemovals));

        Set as;
        Set rs;

        if (clearIntersection || intersection.isEmpty()) {
            physRemovals.removeAll(intersection);
            physAdditions.removeAll(intersection);
            as = physAdditions;
            rs = physRemovals;
        } else {
            // Set up the change sets
            as = new LinkedHashSet<>(physAdditions);
            rs = new LinkedHashSet<>(physRemovals);

            as.removeAll(intersection);
            rs.removeAll(intersection);
        }


        // FIXME additions and removals may have common items! those should be removed in
        // the event's additions / removals sets

        boolean result = false;

        {
            Collection oldValue = self;
            Collection newValue = rawRemovals == self
                    ? physAdditions
                    : Sets.union(Sets.difference(backend, rs), as);

            try {
                vcs.fireVetoableChange(new CollectionChangedEventImpl<>(
                        self, oldValue, newValue,
                        as, rs, Collections.emptySet()));
            } catch (PropertyVetoException e) {
                throw new RuntimeException(e);
            }
        }

        boolean changeByRemoval;
        if (rawRemovals == self) {
            changeByRemoval = !backend.isEmpty();
            if (changeByRemoval) {
                // Only invoke clear if we have to; prevent triggering anything
                backend.clear();
            }
        } else {
            changeByRemoval = backend.removeAll(physRemovals);
        }

        boolean changeByAddition = backend.addAll(physAdditions);
        result = changeByRemoval || changeByAddition;

        {
            Collection oldValue = rawRemovals == self
                    ? physRemovals
                    : Sets.union(Sets.difference(backend, as), rs);
            Collection newValue = self;

            pcs.firePropertyChange(new CollectionChangedEventImpl<>(
                    self, oldValue, newValue,
                    as, rs, Collections.emptySet()));
        }

        return result;
    }

//
//    public static  boolean applyDelta(
//            Collection self,
//            Collection backend,
//            VetoableChangeSupport vcs,
//            PropertyChangeSupport pcs,
//            boolean duplicateAware,
//            Collection rawAdditions, Collection rawRemovals) {
//
//        // Set up the physical removals / additions that will be sent to the backend
//        // This may include overlapping items
//        @SuppressWarnings("unchecked")
//        Collection physRemovals = rawRemovals == self
//            ? StreamOps.collect(duplicateAware, rawRemovals.stream().map(x -> (T)x))
//            : StreamOps.collect(duplicateAware, rawRemovals.stream().filter(backend::contains).map(x -> (T)x));
//        Collection physAdditions = StreamOps.collect(duplicateAware, rawAdditions.stream().filter(x -> !backend.contains(x) || physRemovals.contains(x)));
//
//
//        // Set up the change sets -
//        Set as = new LinkedHashSet<>(physAdditions);
//        Set rs = new LinkedHashSet<>(physRemovals);
//        Set intersection = new LinkedHashSet<>(Sets.intersection(as, rs));
//
//        as.remove(intersection);
//        rs.remove(intersection);
//
//
//
//        // FIXME additions and removals may have common items! those should be removed in
//        // the event's additions / removals sets
//
//        boolean result = false;
//
//        {
//            Collection oldValue = self;
//            Collection newValue = rawRemovals == self
//                    ? physAdditions
//                    : CollectionOps.smartUnion(CollectionOps.smartDifference(backend, physRemovals), physAdditions);
//
//            try {
//                vcs.fireVetoableChange(new CollectionChangedEventImpl<>(
//                        self, oldValue, newValue,
//                        as, rs, Collections.emptySet()));
//            } catch (PropertyVetoException e) {
//                throw new RuntimeException(e);
//            }
//        }
//
//        boolean changeByRemoval;
//        if (rawRemovals == self) {
//            changeByRemoval = !backend.isEmpty();
//            if (changeByRemoval) {
//                // Only invoke clear if we have to; prevent triggering anything
//                backend.clear();
//            }
//        } else {
//            changeByRemoval = backend.removeAll(physRemovals);
//        }
//
//        boolean changeByAddition = backend.addAll(physAdditions);
//        result = changeByRemoval || changeByAddition;
//
//        {
//            Collection oldValue = rawRemovals == self
//                    ? physRemovals
//                    : CollectionOps.smartUnion(CollectionOps.smartDifference(backend, physAdditions), physRemovals);
//            Collection newValue = self;
//
//            pcs.firePropertyChange(new CollectionChangedEventImpl<>(
//                    self, oldValue, newValue,
//                    as, rs, Collections.emptySet()));
//        }
//
//        return result;
//    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy