[431785] Correct synchronization mechanism
[EMFCompare2.git] / plugins / org.eclipse.emf.compare.rcp.ui / src / org / eclipse / emf / compare / rcp / ui / internal / structuremergeviewer / filters / StructureMergeViewerFilter.java
blob5ceaca67bbccaea6762d1a49298971375d92efe5
1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 Obeo.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Obeo - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters;
13 import static com.google.common.base.Predicates.alwaysFalse;
14 import static com.google.common.base.Predicates.not;
15 import static com.google.common.base.Predicates.or;
16 import static com.google.common.collect.Iterables.any;
17 import static com.google.common.collect.Sets.newLinkedHashSet;
19 import com.google.common.base.Predicate;
20 import com.google.common.collect.ImmutableSet;
21 import com.google.common.collect.Iterables;
22 import com.google.common.eventbus.EventBus;
24 import java.util.Collection;
25 import java.util.Set;
27 import org.eclipse.emf.common.notify.Adapter;
28 import org.eclipse.emf.common.notify.Notifier;
29 import org.eclipse.emf.compare.Conflict;
30 import org.eclipse.emf.compare.Match;
31 import org.eclipse.emf.compare.MatchResource;
32 import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.impl.DifferenceFilterChange;
33 import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.provider.GroupItemProviderAdapter;
34 import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDifferenceFilter;
35 import org.eclipse.emf.ecore.EObject;
36 import org.eclipse.emf.edit.tree.TreeNode;
37 import org.eclipse.jface.viewers.Viewer;
38 import org.eclipse.jface.viewers.ViewerFilter;
40 /**
41 * This will be used by the structure viewer to filter out its list of differences according to a number of
42 * provided predicates.
43 * <p>
44 * <b>Note</b> that this filter acts as an "OR" predicate between all provided ones, and that filters are
45 * "exclude" filters. Basically, that means if the user selects two filters, any difference that applies for
46 * any of these two filters will be <i>hidden</i> from the view, contrarily to "classic" {@link ViewerFilter}
47 * that act as "AND" predicates for "include" filters, forcing any displayed element to meet the criterion of
48 * all provided filters.
49 * </p>
51 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
52 * @since 4.0
54 public class StructureMergeViewerFilter extends ViewerFilter {
56 /** A predicate use by default that always returns false. */
57 public static final Predicate<? super EObject> DEFAULT_PREDICATE = alwaysFalse();
59 /** The set of predicates known by this filter. */
60 private final Set<Predicate<? super EObject>> predicates;
62 /** The set of selected filters known by this filter. */
63 private final Set<IDifferenceFilter> selectedDifferenceFilters;
65 /** The set of unselected filters known by this filter. */
66 private final Set<IDifferenceFilter> unselectedDifferenceFilters;
68 /** The {@link EventBus} associated with this filter. */
69 private final EventBus eventBus;
71 /**
72 * The predicate used by this StructureMergeViewerFilter.
74 private final Predicate<? super EObject> viewerPredicate = new Predicate<EObject>() {
75 public boolean apply(EObject eObject) {
76 final boolean ret;
77 if (aggregatedPredicate.apply(eObject)) {
78 Collection<EObject> eContents = eObject.eContents();
79 if (!eContents.isEmpty() && eObject instanceof TreeNode) {
80 EObject data = ((TreeNode)eObject).getData();
81 if (data instanceof Match || data instanceof Conflict || data instanceof MatchResource) {
82 ret = any(eContents, viewerPredicate);
83 } else {
84 ret = true;
86 } else {
87 ret = true;
89 } else {
90 ret = false;
92 return ret;
96 /**
97 * A predicate that aggregates the selected state predicates of selected filters and the unselected state
98 * predicates of unselected filters.
100 private Predicate<? super EObject> aggregatedPredicate;
103 * Constructs the difference filter.
105 * @param eventBus
106 * The {@link EventBus} which will be associated with this filter.
108 public StructureMergeViewerFilter(EventBus eventBus) {
109 this.eventBus = eventBus;
110 this.predicates = newLinkedHashSet();
111 this.selectedDifferenceFilters = newLinkedHashSet();
112 this.unselectedDifferenceFilters = newLinkedHashSet();
113 this.aggregatedPredicate = DEFAULT_PREDICATE;
117 * {@inheritDoc}
119 * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object,
120 * java.lang.Object)
122 @Override
123 public boolean select(Viewer viewer, Object parentElement, Object element) {
124 if (predicates.isEmpty()) {
125 return true;
128 final boolean result;
129 if (element instanceof GroupItemProviderAdapter) {
130 Collection<?> children = ((GroupItemProviderAdapter)element).getChildren(element);
131 result = any(Iterables.filter(children, EObject.class), viewerPredicate);
132 } else if (element instanceof Adapter) {
133 Notifier notifier = ((Adapter)element).getTarget();
134 if (notifier instanceof EObject) {
135 EObject eObject = (EObject)notifier;
136 result = viewerPredicate.apply(eObject);
137 } else {
138 result = true;
140 } else {
141 result = true;
144 return result;
148 * Add the predicate of the given {@link IDifferenceFilter}.
150 * @param filter
151 * The given {@link IDifferenceFilter}.
153 public void addFilter(IDifferenceFilter filter) {
154 boolean changed = predicates.remove(filter.getPredicateWhenUnselected());
155 changed |= predicates.add(filter.getPredicateWhenSelected());
157 changed |= selectedDifferenceFilters.add(filter);
158 changed |= unselectedDifferenceFilters.remove(filter);
160 if (changed) {
161 aggregatedPredicate = computeAggregatedPredicate();
162 eventBus.post(new DifferenceFilterChange(aggregatedPredicate, selectedDifferenceFilters,
163 unselectedDifferenceFilters));
168 * Computes the aggregated predicates composed of selected state predicates of selected filters and
169 * unselected state predicates of unselected filters.
171 * @return an aggregated predicates composed of selected state predicates of selected filters and
172 * unselected state predicates of unselected filters.
174 private Predicate<? super EObject> computeAggregatedPredicate() {
175 return not(or(predicates));
179 * Remove the predicate of the given {@link IDifferenceFilter}.
181 * @param filter
182 * The given {@link IDifferenceFilter}.
184 public void removeFilter(IDifferenceFilter filter) {
185 boolean changed = predicates.add(filter.getPredicateWhenUnselected());
186 changed |= predicates.remove(filter.getPredicateWhenSelected());
188 changed |= unselectedDifferenceFilters.add(filter);
189 changed |= selectedDifferenceFilters.remove(filter);
191 if (changed) {
192 aggregatedPredicate = computeAggregatedPredicate();
193 eventBus.post(new DifferenceFilterChange(aggregatedPredicate, selectedDifferenceFilters,
194 unselectedDifferenceFilters));
199 * Init this StructureMergeViewerFilter.
201 * @param selectedFilters
202 * the set of selected filters known by this filter.
203 * @param unselectedFilters
204 * the set of unselected filters known by this filter.
206 public void init(Collection<IDifferenceFilter> selectedFilters,
207 Collection<IDifferenceFilter> unselectedFilters) {
208 boolean changed = false;
210 if (!predicates.isEmpty()) {
211 predicates.clear();
212 changed = true;
215 for (IDifferenceFilter filter : selectedFilters) {
216 changed |= predicates.add(filter.getPredicateWhenSelected());
217 changed |= selectedDifferenceFilters.add(filter);
219 for (IDifferenceFilter filter : unselectedFilters) {
220 changed |= predicates.add(filter.getPredicateWhenUnselected());
221 changed |= unselectedDifferenceFilters.add(filter);
224 if (changed) {
225 aggregatedPredicate = computeAggregatedPredicate();
226 eventBus.post(new DifferenceFilterChange(aggregatedPredicate, selectedDifferenceFilters,
227 unselectedDifferenceFilters));
232 * Returns the set of selected filters known by this filter.
234 * @return the selectedDifferenceFilters the set of selected filters known by this filter.
236 public Set<IDifferenceFilter> getSelectedDifferenceFilters() {
237 return selectedDifferenceFilters;
241 * Returns the set of unselected filters known by this viewer.
243 * @return the unselectedDifferenceFilters the set of unselected filters known by this viewer.
245 public Set<IDifferenceFilter> getUnSelectedDifferenceFilters() {
246 return ImmutableSet.copyOf(unselectedDifferenceFilters);
250 * Returns the predicate that aggregates the selected state predicates of selected filters and the
251 * unselected state predicates of unselected filters.
253 * @return the predicate that aggregates the selected state predicates of selected filters and the
254 * unselected state predicates of unselected filters.
256 public Predicate<? super EObject> getAggregatedPredicate() {
257 return aggregatedPredicate;