diff --git a/src/org/ntlab/deltaViewer/DeltaLayout.java b/src/org/ntlab/deltaViewer/DeltaLayout.java new file mode 100644 index 0000000..628ab60 --- /dev/null +++ b/src/org/ntlab/deltaViewer/DeltaLayout.java @@ -0,0 +1,179 @@ +package org.ntlab.deltaViewer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.ntlab.deltaExtractor.IAliasCollector; +import org.ntlab.trace.FieldUpdate; +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.MethodInvocation; +import org.ntlab.trace.Reference; +import org.ntlab.trace.Statement; + +import com.mxgraph.model.mxICell; +import com.mxgraph.util.mxPoint; + +public class DeltaLayout implements IObjectLayout { + private mxPoint coordinatorPoint = new mxPoint(0, 100); + + @Override + public void execute(DeltaGraphAdapter mxgraph, IObjectCallGraph objectCallGraph, IAliasCollector aliasCollector) { + Set vertices = mxgraph.getCellToVertexMap().keySet(); + Map idToVertexMap = new HashMap<>(); + for (mxICell vertex: vertices) { + idToVertexMap.put(vertex.getId(), vertex); + } + Statement relatedSt = objectCallGraph.getRelatedPoints().get(0).getStatement(); + String srcObjId = null; + String dstObjId = null; + if (relatedSt instanceof FieldUpdate) { + srcObjId = ((FieldUpdate) relatedSt).getContainerObjId(); + dstObjId = ((FieldUpdate) relatedSt).getValueObjId(); + } else if (relatedSt instanceof MethodInvocation) { + MethodInvocation methodInvStatement = (MethodInvocation) relatedSt; + MethodExecution calledMethodExec = methodInvStatement.getCalledMethodExecution(); + String methodSignature = calledMethodExec.getSignature(); + if (calledMethodExec.isCollectionType() + && (methodSignature.contains("add(") + || methodSignature.contains("set(") + || methodSignature.contains("put(") + || methodSignature.contains("push(") + || methodSignature.contains("addElement("))) { + srcObjId = calledMethodExec.getThisObjId(); + dstObjId = calledMethodExec.getArguments().get(0).getId(); + } else { + return; + } + } else { + return; + } + + // reconstruct srcSide and dstSide + List srcSide = new ArrayList<>(); + List dstSide = new ArrayList<>(); + List references = new ArrayList<>(); + references.addAll(objectCallGraph.getReferences()); + while (references.size() > 0) { + boolean found; + do { + found = false; + for (Reference r: references) { + if (r.getDstObjectId().equals(srcObjId)) { + srcSide.add(r); + references.remove(r); + srcObjId = r.getSrcObjectId(); + found = true; + break; + } + } + } while (found); + do { + found = false; + for (Reference r: references) { + if (r.getDstObjectId().equals(dstObjId)) { + dstSide.add(r); + references.remove(r); + dstObjId = r.getSrcObjectId(); + found = true; + break; + } + } + } while (found); + } + + // layout + double time = 150; + double padding = 200; + coordinatorPoint.setX(coordinatorPoint.getX() + (time * dstSide.size()) + padding); + + // ����(0, 0) + double xCor = coordinatorPoint.getX(); + double yCor = coordinatorPoint.getY(); + + //Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. + List doneList = new ArrayList<>(); + mxgraph.getModel().beginUpdate(); + try { + // Layout vertex object. + // srcSide + int srcSideSize = srcSide.size(); + MethodExecution coordinator = objectCallGraph.getStartPoints().get(0); + String coordinatorObjId = coordinator.getThisObjId(); + String coordinatorClassName = coordinator.getThisClassName(); + for (int i = srcSideSize - 1; i >= 0; i--) { + Reference ref = srcSide.get(i); + if (i == srcSideSize - 1 && !coordinatorObjId.equals(ref.getSrcObjectId()) && !coordinatorClassName.equals(ref.getSrcClassName())) { + System.out.println("coordinator: " + coordinatorClassName + ", " + coordinatorObjId); + coordinatorPoint.setX(coordinatorPoint.getX() + time * 2); + xCor += time * 2; + mxICell vertex = idToVertexMap.get(coordinatorObjId); + setVertexCoordinate(mxgraph, vertex, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i))); + doneList.add(coordinatorObjId); + srcSideSize++; + } + System.out.println("srcSide: " + ref.getSrcClassName() + ", " + ref.isCreation() + ", " + ref.getSrcObjectId()); + if (!ref.isCreation() && !ref.getSrcObjectId().equals(ref.getDstObjectId())) { + if (!doneList.contains(ref.getSrcObjectId())) { + mxICell vertex = idToVertexMap.get(ref.getSrcObjectId()); + setVertexCoordinate(mxgraph, vertex, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i))); + doneList.add(ref.getSrcObjectId()); + } + if (!doneList.contains(ref.getDstObjectId())) { + mxICell vertex = idToVertexMap.get(ref.getDstObjectId()); + setVertexCoordinate(mxgraph, vertex, xCor + (time * (srcSideSize - i)), yCor + (time * (srcSideSize - i))); + doneList.add(ref.getDstObjectId()); + } + } else { + mxICell vertex = idToVertexMap.get(ref.getSrcObjectId()); + setVertexCoordinate(mxgraph, vertex, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i))); + doneList.add(ref.getSrcObjectId()); + doneList.add(ref.getDstObjectId()); + } + } + + // dstSide + int dstSideSize = dstSide.size(); + int cnt = 0; + for (int i = dstSideSize - 1; i >= 0; i--) { + Reference ref = dstSide.get(i); + if (i == dstSideSize - 1 && srcSideSize == 0 && !coordinatorObjId.equals(ref.getSrcObjectId()) && !coordinatorClassName.equals(ref.getSrcClassName())) { + System.out.println("coordinator: " + coordinatorClassName + ", " + coordinatorObjId); + coordinatorPoint.setX(coordinatorPoint.getX() + time * 2); + xCor += time * 2; + System.out.println(coordinatorPoint.getX() + ", " + xCor); + mxICell vertex = idToVertexMap.get(coordinatorObjId); + setVertexCoordinate(mxgraph, vertex, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt))); + doneList.add(coordinatorObjId); + dstSideSize++; + } + System.out.println("dstSide: " + ref.getSrcClassName() + ", " + ref.getDstClassName() + ", " + ref.isCreation()); + if (!ref.isCreation() && !ref.getSrcObjectId().equals(ref.getDstObjectId())) { + if (!doneList.contains(ref.getSrcObjectId())) { + mxICell vertex = idToVertexMap.get(ref.getSrcObjectId()); + setVertexCoordinate(mxgraph, vertex, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt))); + doneList.add(ref.getSrcObjectId()); + cnt++; + } + if (!doneList.contains(ref.getDstObjectId())) { + mxICell vertex = idToVertexMap.get(ref.getDstObjectId()); + setVertexCoordinate(mxgraph, vertex, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt))); + doneList.add(ref.getDstObjectId()); + } + } else { + doneList.add(ref.getDstObjectId()); + } + } + } finally { + mxgraph.getModel().endUpdate(); + } + } + + private void setVertexCoordinate(DeltaGraphAdapter mxgraph, mxICell vertex, double x, double y) { + mxgraph.getCellGeometry(vertex).setX(x); + mxgraph.getCellGeometry(vertex).setY(y); + } + +}