[431785] Correct synchronization mechanism
[EMFCompare2.git] / plugins / org.eclipse.emf.compare.rcp.ui / src / org / eclipse / emf / compare / rcp / ui / internal / structuremergeviewer / filters / impl / DifferenceFilterManager.java
blob50ba2c068c7d6ca335f7dd6bfe2dd1b07ebc23eb
1 /*******************************************************************************
2 * Copyright (c) 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.impl;
13 import com.google.common.base.Function;
14 import com.google.common.base.Joiner;
15 import com.google.common.base.Preconditions;
16 import com.google.common.base.Predicate;
17 import com.google.common.base.Predicates;
18 import com.google.common.collect.Collections2;
19 import com.google.common.collect.Maps;
20 import com.google.common.collect.Sets;
21 import com.google.common.collect.Sets.SetView;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.LinkedHashMap;
26 import java.util.LinkedHashSet;
27 import java.util.Map;
28 import java.util.Set;
30 import org.eclipse.core.runtime.IStatus;
31 import org.eclipse.emf.compare.rcp.internal.extension.impl.ItemUtil;
32 import org.eclipse.emf.compare.rcp.internal.tracer.TracingConstant;
33 import org.eclipse.emf.compare.rcp.ui.EMFCompareRCPUIPlugin;
34 import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDifferenceFilter;
35 import org.osgi.service.prefs.Preferences;
37 /**
38 * Manager of filters.
39 * <p>
40 * This manager handle addition and removal of filters
41 * </p>
42 * <p>
43 * It also allow to override registered filters with preferences.
44 * </p>
46 * @author <a href="mailto:arthur.daussy@obeo.fr">Arthur Daussy</a>
48 public class DifferenceFilterManager {
50 /** Preference key for by default disabled filters. */
51 private static final String BY_DEFAULT_DISABLED_FILTER = "org.eclipse.emf.compare.rcp.ui.filters.disabled"; //$NON-NLS-1$
53 /** A map that associates the class name to theirs {@link IDifferenceFilter}s. */
54 private final Map<String, DifferenceFilterDefaultConfiguration> map;
56 /** The {@link Preferences} holding the value for filter preferences. */
57 private final Preferences preferenceStore;
59 /** Predicate use to transform {@link DifferenceFilterDefaultConfiguration} to {@link IDifferenceFilter}. */
60 private final static Function<DifferenceFilterDefaultConfiguration, IDifferenceFilter> TO_FILTER = new Function<DifferenceFilterManager.DifferenceFilterDefaultConfiguration, IDifferenceFilter>() {
62 public IDifferenceFilter apply(DifferenceFilterDefaultConfiguration arg0) {
63 if (arg0 != null) {
64 return arg0.getFilter();
66 return null;
70 /**
71 * Constructor.
73 * @param preferenceStore
74 * The {@link Preferences} holding the value for filter preferences.
76 public DifferenceFilterManager(Preferences preferenceStore) {
77 map = Collections.synchronizedMap(new LinkedHashMap<String, DifferenceFilterDefaultConfiguration>());
78 this.preferenceStore = preferenceStore;
81 /**
82 * Add a new filter.
84 * @param filter
85 * {@link IDifferenceFilter}
86 * @return The old {@link IDifferenceFilter} register with the same key.
88 IDifferenceFilter add(IDifferenceFilter filter) {
89 Preconditions.checkNotNull(filter);
90 DifferenceFilterDefaultConfiguration oldValue = map.put(filter.getClass().getName(),
91 new DifferenceFilterDefaultConfiguration(filter, filter.defaultSelected()));
92 if (oldValue != null) {
93 return oldValue.getFilter();
95 return null;
98 /**
99 * Remove a filter.
101 * @param className
102 * The class name of the filter.
103 * @return The {@link IDifferenceFilter} that has been removed or <code>null</code> if none.
105 IDifferenceFilter remove(String className) {
106 DifferenceFilterDefaultConfiguration oldValue = map.remove(className);
107 if (oldValue != null) {
108 return oldValue.getFilter();
110 return null;
114 * Get all {@link IDifferenceFilter} that shall be used by default for next comparison.
116 * @return A {@link Set} of {@link IDifferenceFilter} that shall be used by default for next comparison.
118 public Set<IDifferenceFilter> getCurrentByDefaultFilters() {
119 Set<IDifferenceFilter> storedFilter = getDisabledFilters();
120 if (storedFilter == null) {
121 return getInitialByDefaultFilters();
123 return Sets.difference(getAllFilters(), storedFilter);
127 * {@link Set} of {@link IDifferenceFilter} that are initially activated by default.
128 * <p>
129 * During the first addiction in the registry of these {@link IDifferenceFilter},
130 * {@link IDifferenceFilter#defaultSelected()} was equal to true
131 * </p>
133 * @return {@link Set} of {@link IDifferenceFilter} that are original activated by default.
135 public Set<IDifferenceFilter> getInitialByDefaultFilters() {
136 Collection<DifferenceFilterDefaultConfiguration> enableFilter = Collections2.filter(map.values(),
137 new Predicate<DifferenceFilterDefaultConfiguration>() {
139 public boolean apply(DifferenceFilterDefaultConfiguration arg0) {
140 return arg0.isDefaultSelectedInitialValue();
143 return Sets.newLinkedHashSet(Collections2.transform(enableFilter, TO_FILTER));
147 * Set filters that shall be used by default for next comparison.
149 * @param enabledFilter
150 * {@link Set} of {@link IDifferenceFilter} to set.
152 public void setCurrentByDefaultFilters(Set<IDifferenceFilter> enabledFilter) {
153 final Set<IDifferenceFilter> disableFilter;
154 if (enabledFilter == null) {
155 disableFilter = getAllFilters();
156 } else {
157 disableFilter = Sets.difference(getAllFilters(), enabledFilter);
159 SetView<IDifferenceFilter> initialDisabledFilter = Sets.difference(getAllFilters(),
160 getInitialByDefaultFilters());
161 storeInPreferences(disableFilter, initialDisabledFilter);
162 // Trace preferences values
163 if (TracingConstant.CONFIGURATION_TRACING_ACTIVATED) {
164 StringBuilder builder = new StringBuilder();
165 // Print each preferences
166 builder.append("Preference ").append(BY_DEFAULT_DISABLED_FILTER).append(":\n"); //$NON-NLS-1$ //$NON-NLS-2$
167 String preferenceValue = preferenceStore.get(BY_DEFAULT_DISABLED_FILTER, ""); //$NON-NLS-1$
168 String[] groups = preferenceValue.split(ItemUtil.PREFERENCE_DELIMITER);
169 for (int rank = 0; rank < groups.length; rank++) {
170 builder.append(rank).append(". ").append(groups[rank]).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
172 builder.append("\n\n"); //$NON-NLS-1$
173 EMFCompareRCPUIPlugin.getDefault().log(IStatus.INFO, builder.toString());
178 * Get all registered filter.
180 * @return {@link Set} of all filter.
182 public Set<IDifferenceFilter> getAllFilters() {
183 return Sets.newLinkedHashSet(Collections2.transform(map.values(), TO_FILTER));
187 * A {@link Set} of disabled by default {@link IDifferenceFilter} from preferences.
188 * <p>
189 * Those filter will not be activated by default for next comparison
190 * </p>
192 * @return A {@link Set} of disabled by default {@link IDifferenceFilter} from preferences.
194 private Set<IDifferenceFilter> getDisabledFilters() {
195 String diffEngineKey = preferenceStore.get(BY_DEFAULT_DISABLED_FILTER, null);
196 Set<IDifferenceFilter> result = null;
197 if (diffEngineKey != null) {
198 String[] diffEngineKeys = diffEngineKey.split(ItemUtil.PREFERENCE_DELIMITER);
199 for (String nonTrimedKey : diffEngineKeys) {
200 String key = nonTrimedKey.trim();
201 DifferenceFilterDefaultConfiguration descriptor = map.get(key);
202 if (descriptor != null) {
203 if (result == null) {
204 result = new LinkedHashSet<IDifferenceFilter>();
206 result.add(descriptor.getFilter());
210 return result;
214 * Store value in preferences.
216 * @param currentValue
217 * Value to store.
218 * @param defaultConf
219 * Default value.
221 private void storeInPreferences(Set<IDifferenceFilter> currentValue, Set<IDifferenceFilter> defaultConf) {
222 if (currentValue != null && !currentValue.equals(defaultConf)) {
223 Map<String, IDifferenceFilter> toStore = Maps.filterValues(Maps.transformValues(map, TO_FILTER),
224 Predicates.in(currentValue));
225 String preferenceValue = Joiner.on(ItemUtil.PREFERENCE_DELIMITER).join(toStore.keySet());
226 preferenceStore.put(BY_DEFAULT_DISABLED_FILTER, preferenceValue);
227 } else {
228 preferenceStore.remove(BY_DEFAULT_DISABLED_FILTER);
233 * Clear all registered {@link IDifferenceFilter}.
235 public void clear() {
236 map.clear();
240 * Wrapper of {@link IDifferenceFilter} used to keep track of the initial value of
241 * {@link IDifferenceFilter#defaultSelected()} to be able to restore it.
243 * @author <a href="mailto:arthur.daussy@obeo.fr">Arthur Daussy</a>
245 private static class DifferenceFilterDefaultConfiguration {
247 /** Base {@link IDifferenceFilter} */
248 private IDifferenceFilter filter;
250 /** Initial value of {@link IDifferenceFilter#defaultSelected()} during first addition. */
251 private boolean isDefaultSelectedInitialValue;
254 * Constructor.
256 * @param filter
257 * Base filter
258 * @param isByDefaultSelected
259 * Initial value of {@link IDifferenceFilter#defaultSelected()} during first addition.
261 public DifferenceFilterDefaultConfiguration(IDifferenceFilter filter, boolean isByDefaultSelected) {
262 super();
263 this.filter = filter;
264 this.isDefaultSelectedInitialValue = isByDefaultSelected;
268 * @return Base filter.
270 public IDifferenceFilter getFilter() {
271 return filter;
275 * @return Initial value of {@link IDifferenceFilter#defaultSelected()} during first addition.
277 public boolean isDefaultSelectedInitialValue() {
278 return isDefaultSelectedInitialValue;