1 package org.simantics.db.layer0.util;
3 import gnu.trove.map.hash.THashMap;
4 import gnu.trove.set.hash.THashSet;
6 import java.util.ArrayList;
7 import java.util.Collection;
8 import java.util.Collections;
11 import org.simantics.db.ReadGraph;
12 import org.simantics.db.exception.DatabaseException;
15 * <p>HierarchyMultiMap is a multi map whose keys are
16 * partially ordered. When values are asked for a key
17 * all values associated with that key and all its
18 * superkeys are returned. The order of the returned values
19 * is such that values associated with subelements are
20 * in the list before their superelements.</p>
22 * @author Hannu Niemistö
24 public abstract class HierarchyMultiMap<A,B> {
25 THashMap<A, List<B>> map = new THashMap<A, List<B>>();
26 THashMap<A, List<B>> cache;
29 * Associates the value {@code b} with the key {@code a}.
31 public synchronized void put(A a, B b) {
32 List<B> bs = map.get(a);
34 bs = new ArrayList<B>(2);
42 * Gets the values stored into the map for the key {@code a} or
45 public synchronized List<B> get(ReadGraph g, A a) throws DatabaseException {
47 cache = new THashMap<A, List<B>>();
49 List<B> bs = cache.get(a);
51 List<B> base = map.get(a);
52 Collection<A> supers = getImmediateSuperelements(g, a);
56 bs = Collections.emptyList();
57 else if(supers.size() == 1)
58 bs = get(g, supers.iterator().next());
60 THashSet<B> temp = new THashSet<B>();
62 temp.addAll(get(g, s));
63 bs = new ArrayList<B>(temp);
68 if(supers.isEmpty()) {
73 bs = new ArrayList<B>(base);
74 // Filter is used to remove duplicates from the result
75 THashSet<B> filter = new THashSet<B>(base);
81 // Do not store duplicate of the base unnecessarily
82 if(bs.size() == base.size())
93 * Returns the immediate superelements of {@code a}.
94 * @throws DatabaseException
96 protected abstract Collection<A> getImmediateSuperelements(ReadGraph g, A a) throws DatabaseException;
98 protected void sort(List<B> values) {