package Sequenic.T2ext.Selection; import java.util.IdentityHashMap; import java.util.Map; import Sequenic.T2.Coverage.BasicPath; import Sequenic.T2.Seq.Trace; import Sequenic.T2.StreamTraces.TraceFilter; /** * Note: Do NOT use the same instance for both selecting and synthesizing. * * Suppose a certain BasicPath is not modification-traversing, but can not be synthesized. * If synthesizeCoverage is called first the backing selector will be invoked and it will return null. * If isModificationTraversing is subsequently invoked, the cached result is retrieved and * the BasicPath will be marked as modification-traversing, even if it is not. * * Conversely, if isModificationTraversing is invoked first the BasicPath will be cached to * as the 'result'. if synthesizeCoverage is subsequently called, the BasicPath will be returned * unmodified, even if it would otherwise be modified by the backing selector. * * * @author jeiels * */ final class CachedSelector implements ISelector, TraceFilter { private final ISelector selector; private final Map cacheBoolean; private static final int defaultSize = 351; CachedSelector(final ISelector selector) { this.selector = selector; cacheBoolean = new IdentityHashMap(defaultSize); } static CachedSelector create(final ISelector selector, boolean justSelect) { if(justSelect) return new CachedSelector(selector); throw new UnsupportedOperationException("Cached selector does not synthesize"); } public boolean isModificationTraversing(BasicPath bp) { Boolean b = cacheBoolean.get(bp); if(b==null) cacheBoolean.put(bp, b=selector.isModificationTraversing(bp)); return b; } public BasicPath synthesizeCoverage(BasicPath bp) { throw new UnsupportedOperationException("Cached selector does not synthesize"); } public boolean add(Trace t) { final Map cacheBoolean = this.cacheBoolean; for(BasicPath p : t.coverage()) { Boolean b = cacheBoolean.get(p); if(b==null) cacheBoolean.put(p, b=selector.isModificationTraversing(p)); else if(b) return true; } return false; } }