/* * Copyright 2009 Wishnu Prasetya. * * This file is part of T2. * T2 is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License (GPL) as published by the * Free Software Foundation; either version 3 of the License, or any * later version. * * T2 is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * A copy of the GNU General Public License can be found in T2 distribution. * If it is missing, see http://www.gnu.org/licenses. */ package Sequenic.T2ext.Instrumenter; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import Sequenic.T2.Coverage.BasicPath; /** * Represent a path through a CFG, as observed from injected sensors. * * @author Wishnu Prasetya * */ public class ObservedPath { /** * The unique name of the target method. This name is assigned when * the method was instrumented. */ String methodUname ; long runID ; /** * The nodes in the path. Each node will be just represented by its ID * (this is what we get from a sensor). */ LinkedList nodes = new LinkedList() ; /** * The same path represented as a list of edges. */ LinkedList> edges = new LinkedList>() ; public ObservedPath(String mname, long runid) { methodUname = mname.intern(); runID = runid; } public void extend(int nodeId){ if (nodes.isEmpty()) { nodes.add(nodeId) ; return ; } Integer lastNode = nodes.getLast() ; nodes.add(nodeId) ; edges.add(new Edge(lastNode,nodeId)) ; } public void clear() { nodes.clear() ; edges.clear() ; } public String getMethodUname() { return methodUname; } public LinkedList getNodes() { return nodes; } /** Returns an EqObject backed by this ObservedPath that overrides hashCode and equals. * Two EqObjects are equal if and only if their backing ObservedPaths have * equivalent methodNames and Nodes. * * The object is suitable for use in HashSets and HashMaps. * * Note that the ObservedPath should not modified after this method is called, * otherwise the contracts of hashCode and equals will be violated. * * @return */ public Object getEqObject() { return new EqObject(); } private final class EqObject { private boolean equals(String mName, Iterator path) { if(!mName.equals(methodUname)) return false; Iterator a = nodes.iterator(); while(a.hasNext()) if(!path.hasNext() || a.next().intValue() != path.next().intValue()) return false; return !path.hasNext(); } @Override public boolean equals(Object obj) { if(obj instanceof EqObject) return ((EqObject) obj).equals(methodUname, nodes.iterator()); else return false; } @Override public int hashCode() { return methodUname.hashCode()+nodes.getLast(); } } public BasicPath pickle() { int[] path = new int[nodes.size()]; int t = 0; for(Integer i : nodes) path[t++] = i.intValue(); return BasicPath.create(methodUname, path); } public static final class CachingPickleFactory { private final Map cache = new HashMap(); public BasicPath pickle(ObservedPath p) { Object key = p.getEqObject(); BasicPath value = cache.get(key); if(value==null) { value = p.pickle(); cache.put(key, value); } return value; } } }