package Sequenic.T2ext.Selection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; interface PathSelector { public boolean select(int[] path); public int[] synthesize(int[] path); public static final PathSelector ALWAYS = new PathSelector() { public int[] synthesize(int[] path){ return null; } public boolean select(int[] path){ return true; } @Override public String toString() { return "PathSelector.ALWAYS";} }; public static final PathSelector NEVER = new PathSelector() { public int[] synthesize(int[] path){ return path; } public boolean select(int[] path){ return false; } @Override public String toString() { return "PathSelector.NEVER";} }; /** A class to incrementally build a PathSelector * * @author Jeiel Schalkwijk * */ final static class Factory { private Map relabel = new HashMap(); private Set dangerousEdges = new HashSet(); void markDangerous(int srcId, int targetId) { HashEqualsEdge edge = HashEqualsEdge.weakCache.make(srcId, targetId); if(dangerousEdges.add(edge)) //dangerous edges are never relabeled relabel.remove(edge); } void relabelIfNeeded(int origId, int origChildId, int modChildId) { if(origChildId!=modChildId) { HashEqualsEdge key = HashEqualsEdge.weakCache.make(origId, origChildId); if(dangerousEdges.contains(key)) //dangerous edges are never relabeled return; //Can not relabel the same edge to two different modChilds //In this case retesting is needed, even if the path is not modification-traversing if(relabel.containsKey(key) && relabel.get(key).intValue()!=modChildId) { modChildId = -1; } relabel.put(key, modChildId); } } void relabelStartNodeIfNeeded(int origStartId, int modStartId) { if(origStartId != modStartId) relabel.put(null, modStartId); } PathSelector resetAndReturn() { PathSelector ret; switch (dangerousEdges.size()) { case 0: ret = PathSelector.NEVER; break; case 1: ret = new DangerousEdgesSelector( Collections.singleton(dangerousEdges.iterator().next()) ); dangerousEdges.clear(); break; default: ret = new DangerousEdgesSelector(dangerousEdges); dangerousEdges = new HashSet(); } if(!relabel.isEmpty()) { ret = new Relabeller(relabel, ret); relabel = new HashMap(); } return ret; } } static final class DangerousEdgesSelector extends HashEqualsEdge implements PathSelector { private final Set dangerousEdges; public DangerousEdgesSelector(final Set dangerousEdges) { this.dangerousEdges = dangerousEdges; } public boolean select(int[] path) { if(path.length>1) { edge = path[0]; for(int i = 1; i mappings; private final PathSelector dangerousSelector; public Relabeller(final Map mappings, final PathSelector dangerousSelector) { this.mappings = mappings; this.dangerousSelector = dangerousSelector; } public boolean select(int[] path) { return dangerousSelector.select(path); } private int[] copyPath(int[] path) { int[] newPath = new int[path.length]; System.arraycopy(path, 0, newPath, 0, path.length); if(mappings.containsKey(null)) newPath[0] = mappings.get(null); return newPath; } public int[] synthesize(final int[] path) { if(dangerousSelector.select(path)) return null; if(path.length==0) return path; int[] newPath = null; edge = path[0]; for(int i = 1; i