package org.simantics.db.common.recursive; import java.util.Collections; import java.util.Set; import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import gnu.trove.set.hash.THashSet; /** * Finds all roots reachable by {@code children} function */ public abstract class FindRoots extends CachedRecursiveSearch> { protected abstract boolean isRoot(Resource resource) throws DatabaseException; protected Set getSourceValue(Resource resource) throws org.simantics.db.exception.DatabaseException { if(isRoot(resource)) return Collections.singleton(resource); else return null; } private static int sharedElements(Set a, Set b) { int count = 0; for(Resource r : a) if(b.contains(r)) ++count; return count; } @Override protected Set combineNotNull(Set a, Set b) throws DatabaseException { int aSize = a.size(); int bSize = b.size(); int shared; if(aSize <= bSize) { shared = sharedElements(a, b); if(aSize == shared) return b; } else { shared = sharedElements(b, a); if(bSize == shared) return a; } // Both set contain elements not in the other set THashSet combined = new THashSet(aSize + bSize - shared); combined.addAll(a); combined.addAll(b); return combined; } }