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
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
;
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
;
41 * This will be used by the structure viewer to filter out its list of differences according to a number of
42 * provided predicates.
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.
51 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
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
;
72 * The predicate used by this StructureMergeViewerFilter.
74 private final Predicate
<?
super EObject
> viewerPredicate
= new Predicate
<EObject
>() {
75 public boolean apply(EObject eObject
) {
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
);
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.
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
;
119 * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object,
123 public boolean select(Viewer viewer
, Object parentElement
, Object element
) {
124 if (predicates
.isEmpty()) {
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
);
148 * Add the predicate of the given {@link IDifferenceFilter}.
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
);
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}.
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
);
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()) {
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
);
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
;