diff options
author | Philip Langer | 2018-01-23 14:21:23 +0000 |
---|---|---|
committer | Laurent Goubet | 2018-05-01 09:28:05 +0000 |
commit | 4d22fbc2c19a878fc9f4dd5ac400c58808ea2c09 (patch) | |
tree | ae2106056b098eb1f2bad366cc14f0fe3e67b442 | |
parent | c5fe2c107fed82573600af099767d6f4c42effc7 (diff) | |
download | org.eclipse.emf.compare-4d22fbc2c19a878fc9f4dd5ac400c58808ea2c09.tar.gz org.eclipse.emf.compare-4d22fbc2c19a878fc9f4dd5ac400c58808ea2c09.tar.xz org.eclipse.emf.compare-4d22fbc2c19a878fc9f4dd5ac400c58808ea2c09.zip |
Improve IMerger registry implementation
The RegistryImpl maintains a map of registered mergers that must be
repeatedly sorted on each lookup. Better would be to maintain the
registered mergers in a list that is already sorted so that the sorting
cost is paid once per add rather than once per lookup. This way
getMergersByRankDescending can call basicGetMergers which returns an
already-sorted result and even getMergers will return a sorted result,
enough though the API doesn't require that and the old implementation
returned a random/arbitrarily ordered result.
Change-Id: I1ac87627f0f27b5dccef735ac4be40b32148fe53
Signed-off-by: Philip Langer <planger@eclipsesource.com>
-rw-r--r-- | plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java | 74 |
1 files changed, 51 insertions, 23 deletions
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java index a6bf4b5a8..f0adbc0f1 100644 --- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java +++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2015 Obeo and others. + * Copyright (c) 2012, 2018 Obeo and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -19,14 +19,12 @@ import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterators; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.emf.common.util.Monitor; import org.eclipse.emf.compare.Diff; @@ -191,13 +189,13 @@ public interface IMerger { /** * Map which references the registered mergers per their class name. */ - private final Map<String, IMerger> map; + private final List<IMerger> registeredMergers; /** * Constructor. */ public RegistryImpl() { - map = new ConcurrentHashMap<String, IMerger>(); + registeredMergers = new CopyOnWriteArrayList<>(); } /** @@ -273,8 +271,28 @@ public interface IMerger { */ public IMerger add(IMerger merger) { Preconditions.checkNotNull(merger); + IMerger result = null; merger.setRegistry(this); - return map.put(merger.getClass().getName(), merger); + final String mergerClassName = merger.getClass().getName(); + for (IMerger registeredMerger : registeredMergers) { + String registeredMergerClassName = registeredMerger.getClass().getName(); + if (registeredMergerClassName.equals(mergerClassName)) { + result = registeredMerger; + registeredMergers.remove(result); + break; + } + } + + registeredMergers.add(merger); + + Collections.sort(registeredMergers, new Comparator<IMerger>() { + public int compare(IMerger o1, IMerger o2) { + // Sort from largest to smallest + return o2.getRanking() - o1.getRanking(); + } + }); + + return result; } /** @@ -283,11 +301,15 @@ public interface IMerger { * @see org.eclipse.emf.compare.merge.IMerger.Registry#remove(java.lang.String) */ public IMerger remove(String className) { - IMerger previous = map.remove(className); - if (previous != null) { - previous.setRegistry(null); + for (IMerger registeredMerger : registeredMergers) { + String registeredMergerClassName = registeredMerger.getClass().getName(); + if (registeredMergerClassName.equals(className)) { + registeredMerger.setRegistry(null); + registeredMergers.remove(registeredMerger); + return registeredMerger; + } } - return previous; + return null; } /** @@ -296,7 +318,10 @@ public interface IMerger { * @see org.eclipse.emf.compare.merge.IMerger.Registry#clear() */ public void clear() { - map.clear(); + for (IMerger registeredMerger : registeredMergers) { + registeredMerger.setRegistry(null); + } + registeredMergers.clear(); } /** @@ -324,14 +349,7 @@ public interface IMerger { * @since 3.3 */ public Iterator<IMerger> getMergersByRankDescending(Diff diff, final IMergeCriterion criterion) { - List<IMerger> mergers = new ArrayList<IMerger>(getMergers(diff)); - Collections.sort(mergers, new Comparator<IMerger>() { - public int compare(IMerger o1, IMerger o2) { - // Sort from largest to smallest - return o2.getRanking() - o1.getRanking(); - } - }); - return Iterators.filter(mergers.iterator(), new Predicate<IMerger>() { + return Iterators.filter(basicGetMergers(diff).iterator(), new Predicate<IMerger>() { public boolean apply(IMerger input) { if (input instanceof IMergeCriterionAware) { if (((IMergeCriterionAware)input).apply(criterion)) { @@ -350,15 +368,25 @@ public interface IMerger { * @see org.eclipse.emf.compare.merge.IMerger.Registry#getMergers(org.eclipse.emf.compare.Diff) */ public Collection<IMerger> getMergers(Diff target) { + return newArrayList(basicGetMergers(target)); + } + + /** + * Returns the sorted mergers (by rank descending) applicable for the target diff. + * + * @param target + * the target diff. + * @return the sorted mergers applicable for the target diff. + */ + private Iterable<IMerger> basicGetMergers(Diff target) { final Predicate<IMerger> mergerFor; if (target == null) { mergerFor = Predicates.alwaysTrue(); } else { mergerFor = isMergerFor(target); } - Iterable<IMerger> mergers = filter(map.values(), mergerFor); - List<IMerger> ret = newArrayList(mergers); - return ret; + Iterable<IMerger> mergers = filter(registeredMergers, mergerFor); + return mergers; } } } |