package org.ntlab.deltaViewer;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JFrame;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.DirectedWeightedPseudograph;
import org.ntlab.deltaExtractor.Alias;
import org.ntlab.deltaExtractor.Delta;
import org.ntlab.deltaExtractor.ExtractedStructure;
import org.ntlab.deltaExtractor.AliasPair;
import org.ntlab.deltaViewer.Edge.TypeName;
import org.ntlab.deltaExtractor.Alias.AliasType;
import org.ntlab.trace.ArrayAccess;
import org.ntlab.trace.ArrayUpdate;
import org.ntlab.trace.FieldAccess;
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.canvas.mxGraphics2DCanvas;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxICell;
import com.mxgraph.shape.mxConnectorShape;
import com.mxgraph.shape.mxIShape;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.view.mxInteractiveCanvas;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxGraphView;
/**
* Make and display JGraph of extracted delta.
*
* @author Nitta Lab.
*/
//TASK: bArray O
//Careful: Parent
//BUG: methodExecution Id. O
//BUG: Move ObjectVertex position sometimes. O
//BUG: Resize ObjectVertex sometimes. O
//BUG: finally field reference. O
//BUG: edge drawing order. -> parent
//BUG: methodExecution drawing order. -> parent
//BUG: ObjectVertex position when Resize ObjectVertex. O
public class DeltaViewer {
private static Dimension DEFAULT_SIZE = new Dimension(700, 700);
private static String WINDOW_TITLE = "Delta Viewer";
private ExtractedStructure eStructure;
private DeltaAliasCollector deltaAliasCollector;
private Map<String, ObjectVertex> objectToVertexMap = new HashMap<>();
private Map<MethodExecution, MethodExecutionVertex> methodExecToVertexMap = new LinkedHashMap<>();
private Map<String, Edge> edgeMap = new HashMap<>();
private JFrame frame;
private DeltaGraphAdapter mxgraph;
// No clue what this does but it is needed.
private mxICell mxDefaultParent;
private mxGraphComponent mxgraphComponent;
private int curFrame = 0;
private static Dimension VERTEX_OBJECT_SIZE = new Dimension(70, 70);
private static Dimension VERTEX_METHOD_EXECUTION_SIZE = new Dimension(55, 20);
private mxPoint coordinatorPoint = new mxPoint(DEFAULT_SIZE.getWidth() / 2 + 75, 100);
private DeltaAnimation deltaAnimation;
private double scale = 1;
public DeltaViewer() {
mxgraph = new DeltaGraphAdapter(new DirectedWeightedPseudograph(DefaultEdge.class));
mxDefaultParent = (mxCell)mxgraph.getDefaultParent();
mxgraphComponent = new mxGraphComponent(mxgraph) {
public mxInteractiveCanvas createCanvas() {
return new CurvedCanvas(this);
}
};
deltaAnimation = new DeltaAnimation(mxgraph, mxgraphComponent);
}
public DeltaViewer(ExtractedStructure extractedStructure, DeltaAliasCollector deltaAliasCollector) {
this();
this.eStructure = extractedStructure;
this.deltaAliasCollector = deltaAliasCollector;
// init();
}
/** Initialize JFrame, make vertex object and edge object. */
public void init() {
// Build a frame, create a graph, and add the graph to the frame so you can actually see the graph.
if(eStructure != null) {
List<Reference> srcSide = eStructure.getDelta().getSrcSide();
List<Reference> dstSide = eStructure.getDelta().getDstSide();
if (srcSide.size() >= 1 && dstSide.size() >= 1) {
WINDOW_TITLE = "extract delta of:" + eStructure.getDelta().getSrcSide().get(0).getDstClassName() + "(" + eStructure.getDelta().getSrcSide().get(0).getDstObjectId() + ")" + " -> " + eStructure.getDelta().getDstSide().get(0).getDstClassName() + "(" + eStructure.getDelta().getDstSide().get(0).getDstObjectId() + ")";
}
}
frame = new JFrame(WINDOW_TITLE);
frame.setSize(DEFAULT_SIZE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mxgraphComponent, BorderLayout.CENTER);
frame.setVisible(true);
createObjectVertices(eStructure);
createEdgeToObject(deltaAliasCollector.getAliasList(), deltaAliasCollector.getAliasPairList());
// Fit graph size in visible JFrame.
mxGraphView view = mxgraphComponent.getGraph().getView();
int componentWidth = mxgraphComponent.getWidth() - 25;
double viewWidth = (double) view.getGraphBounds().getWidth();
// Object component = mxgraph.insertDeltaVertex(mxDefaultParent, "component", "component", "fillColor=white"); //creates a white vertex.
// ((mxICell)component).getGeometry().setX(mxgraphComponent.getWidth() - 30);
// ((mxICell)component).getGeometry().setY(10);
// Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, "view", "view", "fillColor=white"); //creates a white vertex.
// ((mxICell)vertex).getGeometry().setX(view.getGraphBounds().getWidth());
// ((mxICell)vertex).getGeometry().setY(10);
System.out.print("Scale " + componentWidth + ", " + viewWidth + ", " + coordinatorPoint.getX());
if (viewWidth < coordinatorPoint.getX()) {
viewWidth += coordinatorPoint.getX();
}
// scale = (double)componentWidth/viewWidth;
System.out.println(", " + scale);
// scale = 1.5;
view.setScale(scale);
deltaAnimation.setScale(scale);
update();
}
/** Update graph on JFrame and set Cell style. */
public void update() {
setCellsStyle();
mxgraphComponent.refresh();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void setExtractedStructure(ExtractedStructure extractedStructure) {
this.eStructure = extractedStructure;
}
public void setDeltaAliasCollector(DeltaAliasCollector deltaAliasCollector) {
this.deltaAliasCollector = deltaAliasCollector;
}
public void setFrameSize(int width, int height) {
DEFAULT_SIZE.setSize(width, height);
}
public void setCoordinatorPoint(double x, double y) {
coordinatorPoint.setX(x);
coordinatorPoint.setY(y);
}
/** Set style of All cells. */
private void setCellsStyle() {
List<Object> vertexObject = new ArrayList<>();
List<Object> staticVertexObject = new ArrayList<>();
List<Object> alignMiddleVertex = new ArrayList<>();
List<Object> alignTopVertex = new ArrayList<>();
List<Object> edgeObject = new ArrayList<>();
List<Object> edgeObjectCreate = new ArrayList<>();
List<Object> edgeMethodExec = new ArrayList<>();
List<Object> roundEdge = new ArrayList<>();
for (Entry<String, ObjectVertex> objectToVertexEntry: objectToVertexMap.entrySet()) {
String key = objectToVertexEntry.getKey();
ObjectVertex objectVertex = objectToVertexEntry.getValue();
if (key.matches("0")) {
staticVertexObject.add(objectVertex.getCell());
} else {
vertexObject.add(objectVertex.getCell());
}
if(objectVertex.getVertexMethodExecutions().size() == 0) {
alignMiddleVertex.add(objectVertex.getCell());
} else {
alignTopVertex.add(objectVertex.getCell());
}
}
List<MethodExecutionVertex> vertexMethodExecList = new ArrayList<>(methodExecToVertexMap.values());
Collections.reverse(vertexMethodExecList);
for (int i = 0; i < vertexMethodExecList.size(); i++) {
switch(i) {
case 0:
((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ff7fbf");
break;
case 1:
((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ff99cc");
break;
case 2:
((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ffb2d8");
break;
case 3:
((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ffcce5");
break;
case 4:
((mxICell)vertexMethodExecList.get(i).getCell()).setStyle("fillColor=#ffe0ef");
break;
default:
break;
}
}
for (Edge edge: edgeMap.values()) {
roundEdge.add(edge.getCell());
switch(edge.getTypeName()) {
case Reference:
edgeObject.add(edge.getCell());
break;
case Create:
edgeObject.add(edge.getCell());
edgeObjectCreate.add(edge.getCell());
break;
case Call:
edgeMethodExec.add(edge.getCell());
break;
default:
break;
}
}
/*Given a cell, we can change it's style attributes, for example the color. NOTE that you have to call the graphComponent.refresh() function, otherwise you won't see the difference! */
mxgraph.setCellStyles(mxConstants.STYLE_SHAPE, mxConstants.SHAPE_ELLIPSE, vertexObject.toArray(new Object[vertexObject.size()]));
mxgraph.setCellStyles(mxConstants.STYLE_PERIMETER, mxConstants.PERIMETER_ELLIPSE, vertexObject.toArray(new Object[vertexObject.size()]));
mxgraph.setCellStyleFlags(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_UNDERLINE, true, vertexObject.toArray(new Object[vertexObject.size()]));
mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE, alignMiddleVertex.toArray(new Object[alignMiddleVertex.size()]));
mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP, alignTopVertex.toArray(new Object[alignTopVertex.size()]));
mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_TOPTOBOTTOM, edgeObject.toArray(new Object[edgeObject.size()]));
mxgraph.setCellStyleFlags(mxConstants.STYLE_DASHED, 1, true, edgeObjectCreate.toArray(new Object[edgeObjectCreate.size()]));
// mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_ENTITY_RELATION, edgeObject.toArray(new Object[edgeObject.size()]));
// mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_ORTHOGONAL, edgeObject.toArray(new Object[edgeObject.size()]));
mxgraph.setCellStyleFlags(mxConstants.STYLE_ROUNDED, 1, true, roundEdge.toArray(new Object[roundEdge.size()]));
mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_TOP, roundEdge.toArray(new Object[roundEdge.size()]));
mxgraph.setCellStyles(mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_BOTTOM, roundEdge.toArray(new Object[roundEdge.size()]));
// mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.SHAPE_CURVE, edgeObject.toArray(new Object[edgeObject.size()]));
mxgraph.setCellStyles(mxConstants.STYLE_STROKECOLOR, "#008000", edgeMethodExec.toArray(new Object[edgeMethodExec.size()]));
mxgraph.setCellStyleFlags(mxConstants.STYLE_DASHED, 1, true, edgeMethodExec.toArray(new Object[edgeMethodExec.size()]));
// mxgraph.setCellStyleFlags(mxConstants.STYLE_AUTOSIZE, 1, true, vertexObject.toArray(new Object[vertexObject.size()]));
// mxgraph.setCellStyles(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_ORTHOGONAL, edgeMethodExec.toArray(new Object[edgeMethodExec.size()]));
// mxgraph.setCellStyles(mxConstants.STYLE_ELBOW, mxConstants.ELBOW_VERTICAL, edgeMethodExec.toArray(new Object[edgeMethodExec.size()]));
}
// private double getXForCell(String id) {
// double res = -1;
// if (objectToVertexMap.containsKey(id)) {
// Object cell = objectToVertexMap.get(id).getCell();
// res = mxgraph.getCellGeometry(cell).getX();
// }
// return res;
// }
// private double getYForCell(String id) {
// double res = -1;
// if (objectToVertexMap.containsKey(id)) {
// Object cell = objectToVertexMap.get(id).getCell();
// res = mxgraph.getCellGeometry(cell).getY();
// }
// return res;
// }
// private mxICell getRootParentCell(Object object) {
// mxICell cell = (mxICell) object;
// if(cell.getParent().getValue() == null) {
// return cell;
// }
// return getRootParentCell(cell.getParent());
// }
/**
* Whether sourceCell parents contain targetCell
* @param sourceCell
* @param targetCell
* @return
*/
private boolean isParent(mxICell sourceCell, mxICell targetCell) {
mxICell sourceParentCell = sourceCell.getParent();
if (sourceParentCell == null || sourceParentCell.getValue() == null) {
return false;
}
if (sourceParentCell == targetCell) {
return true;
}
System.out.println(sourceCell.getId() + ", " + sourceParentCell.getId());
return isParent(sourceParentCell, targetCell);
}
private Point getAbsolutePointforCell(mxICell cell) {
Point p1 = cell.getGeometry().getPoint();
if(cell.getParent().getValue() == null || cell == cell.getParent()) {
return p1;
}
System.out.println(cell.getId() + ", " + cell.getParent().getId());
Point p2 = getAbsolutePointforCell(cell.getParent());
return new Point((int) (p1.getX() + p2.getX()), (int) (p1.getY() + p2.getY()));
}
/**
* Step to animation of specified alias.
*
* @param alias Alias type and occurrence point etc.
*/
public void stepToAnimation(Alias alias) {
try {
stepToAnimation(deltaAliasCollector.getAliasList().indexOf(alias));
} catch (IndexOutOfBoundsException e) {
stepToAnimation(-1);
}
}
/**
* Parent : Step to animation of specified numFrame.
*
* @param numFrame Current animation frame.
*/
public void stepToAnimation(int numFrame) {
if (deltaAliasCollector.getAliasList().size() > numFrame) {
doAnimation(curFrame, numFrame);
} else if (deltaAliasCollector.getAliasList().size() == numFrame){
System.out.println("\r\nLast Animation.");
doLastAnimation(numFrame);
} else {
System.out.println("ERROR : Not exist alias.");
}
}
/**
* Do animation from fromFrame to toFrame.
*
* @param fromFrame
* @param toFrame
*/
private void doAnimation(int fromFrame, int toFrame) {
for (int i = fromFrame; i <= toFrame; i++) {
List<Alias> aliasList = new ArrayList<>(deltaAliasCollector.getAliasList());
Alias alias = aliasList.get(i);
System.out.println("\r\n" + i + ": " + alias.getAliasType().toString());
System.out.println(alias.getObjectId() + ", " + alias.getMethodSignature() + " l." + alias.getLineNo());
switch(alias.getAliasType()) {
case RETURN_VALUE:
moveObjectVertex(alias);
update();
break;
case METHOD_INVOCATION:
removeMethodExecutionVertex(alias);
moveObjectVertex(alias);
update();
break;
case CONSTRACTOR_INVOCATION:
createObjectVertexOnConstractor(alias);
createMethodExecutionVertex(alias, ((MethodInvocation)alias.getOccurrencePoint().getStatement()).getCallerSideMethodName(), ((MethodInvocation)alias.getOccurrencePoint().getStatement()).getCalledMethodExecution());
update();
removeMethodExecutionVertex(alias);
update();
break;
case FORMAL_PARAMETER:
moveObjectVertex(alias);
update();
break;
case ACTUAL_ARGUMENT:
moveObjectVertex(alias);
update();
break;
case THIS:
if (curFrame == 0 || alias.getObjectId().matches("0")) {
createMethodExecutionVertex(alias);
update();
}
break;
case RECEIVER:
// Make VertexMethodExecution of called method execution.
MethodExecution calledMethodExec = ((MethodInvocation) alias.getOccurrencePoint().getStatement()).getCalledMethodExecution();
if (!methodExecToVertexMap.containsKey(calledMethodExec)) {
createMethodExecutionVertex(alias, calledMethodExec.getSignature(), calledMethodExec);
update();
}
break;
default:
break;
}
curFrame = i + 1;
outputLog();
}
}
/**
* Make last animation of extracted delta.
*
* @param numFrame AliasList size.
*/
private void doLastAnimation(int numFrame) {
outputLog();
curFrame = numFrame;
Alias alias = deltaAliasCollector.getAliasList().get(numFrame - 1);
// Make ObjectEdge and reset position of vertexObject, remove vertexMethodExecution.
for(Statement statement: alias.getMethodExecution().getStatements()) {
if(statement instanceof FieldUpdate) {
// Format fieldName.
FieldUpdate fieldUpdateStatement = (FieldUpdate) statement;
String fieldNames[] = formatFieldName(fieldUpdateStatement.getFieldName());
String fieldName = fieldNames[fieldNames.length-1];
String sourceObjectId = fieldUpdateStatement.getContainerObjId();
createObjectRefrence(fieldUpdateStatement, fieldName);
// Change!
String targetObjectId = fieldUpdateStatement.getValueObjId();
ObjectVertex targetObjectVertex = objectToVertexMap.get(targetObjectId);
MethodExecution calledMethodExec = alias.getMethodExecution();
if (methodExecToVertexMap.containsKey(calledMethodExec)) {
if (methodExecToVertexMap.get(calledMethodExec).getLocals().contains(targetObjectVertex)) {
methodExecToVertexMap.get(calledMethodExec).getLocals().remove(targetObjectVertex);
System.out.println(methodExecToVertexMap.get(calledMethodExec).getLabel() + " :removeLocal: " + targetObjectVertex.getLabel());
} else if (methodExecToVertexMap.get(calledMethodExec).getArguments().contains(targetObjectVertex)) {
methodExecToVertexMap.get(calledMethodExec).getArguments().remove(targetObjectVertex);
System.out.println(methodExecToVertexMap.get(calledMethodExec).getLabel() + " :removeArgument: " + targetObjectVertex.getLabel());
}
}
removeCalledMethodExecutionVertex(objectToVertexMap.get(sourceObjectId), alias.getMethodExecution().getCallerMethodExecution(), alias.getMethodExecution());
updateObjectVertices();
ObjectVertex targetParentObjVertex = objectToVertexMap.get(calledMethodExec.getThisObjId());
deltaAnimation.setVertexAnimation((mxCell)targetParentObjVertex.getCell(), new mxPoint(targetParentObjVertex.getInitialX(), targetParentObjVertex.getInitialY()));
deltaAnimation.startVertexAnimation();
}
if(statement instanceof MethodInvocation) {
MethodInvocation methodInvocationStatement = (MethodInvocation) statement;
MethodExecution methodExec = methodInvocationStatement.getCalledMethodExecution();
//ArrayやListのときだけラベルを付ける(確実に分かっているものとき)getSignature->contains("List.get(") || "Map.get(") <ホワイトリスト>
if (methodExec.getSignature().contains("List.add(") ||
methodExec.getSignature().contains("Map.put(")) {
String sourceObjectId = methodExec.getThisObjId();
createObjectRefrence(methodExec);
// Change!
String targetObjectId = methodExec.getArguments().get(0).getId();
ObjectVertex targetObjectVertex = objectToVertexMap.get(targetObjectId);
MethodExecution calledMethodExec = alias.getMethodExecution();
if (methodExecToVertexMap.containsKey(calledMethodExec)) {
if (methodExecToVertexMap.get(calledMethodExec).getLocals().contains(targetObjectVertex)) {
methodExecToVertexMap.get(calledMethodExec).getLocals().remove(targetObjectVertex);
System.out.println(methodExecToVertexMap.get(calledMethodExec).getLabel() + " :removeLocal: " + targetObjectVertex.getLabel());
} else if (methodExecToVertexMap.get(calledMethodExec).getArguments().contains(targetObjectVertex)) {
methodExecToVertexMap.get(calledMethodExec).getArguments().remove(targetObjectVertex);
System.out.println(methodExecToVertexMap.get(calledMethodExec).getLabel() + " :removeArgument: " + targetObjectVertex.getLabel());
}
}
removeCalledMethodExecutionVertex(objectToVertexMap.get(sourceObjectId), alias.getMethodExecution().getCallerMethodExecution(), alias.getMethodExecution());
updateObjectVertices();
}
}
}
// MethodExecution tempMethodExec = alias.getMethodExecution();
// //ArrayやListのときだけラベルを付ける(確実に分かっているものとき)getSignature->contains("List.get(") || "Map.get(") <ホワイトリスト>
// if (tempMethodExec.getSignature().contains("List.add(") ||
// tempMethodExec.getSignature().contains("Map.put(")) {
// String srcClassName = tempMethodExec.getThisClassName();
// String fieldName = tempMethodExec.getArguments().get(0).getId();
// System.out.println("rTHIS " + srcClassName + ", " + fieldName);
// }
// Statement tempStatement = alias.getOccurrencePoint().getStatement(); -> MethodInvocation
// if(tempStatement instanceof FieldAccess) {
// FieldAccess fieldAccessStatement = (FieldAccess) tempStatement;
// String fieldNames[] = formatFieldName(fieldAccessStatement.getFieldName());
// String srcClassName = fieldNames[0];
// String fieldName = fieldNames[1];
// String sourceObjectId = fieldAccessStatement.getContainerObjId();
// System.out.println(fieldName);
// createObjectRefrence(fieldAccessStatement, fieldName);
// removeCalledMethodExecutionVertex(objectToVertexMap.get(sourceObjectId), alias.getMethodExecution().getCallerMethodExecution(), alias.getMethodExecution());
// updateObjectVertices();
// }
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
List<MethodExecution> methodExecList = new ArrayList<>(methodExecToVertexMap.keySet());
Collections.reverse(methodExecList);
System.out.println(methodExecList.size());
for(int i = 0; i < methodExecList.size(); i++) {
String objectId = methodExecList.get(i).getThisObjId();
ObjectVertex sourceVertexObject = objectToVertexMap.get(objectId); // sourceVertex
MethodExecution methodExec = methodExecList.get(i);
if (i != methodExecList.size()-1) {
for(Statement statement: methodExec.getStatements()) {
if(statement instanceof MethodInvocation) {
MethodExecution calledMethodExec = ((MethodInvocation) statement).getCalledMethodExecution();
String calledObjectId = calledMethodExec.getThisObjId();
System.out.println(calledObjectId);
if(objectToVertexMap.containsKey(calledObjectId)) {
mxICell calledCell = (mxICell)objectToVertexMap.get(calledObjectId).getCell();
Point absolutePointCalledCell = getAbsolutePointforCell(calledCell);
System.out.println(objectId + ", " + methodExec.getSignature());
// objectToVertexMap.get(calledObjectId).resetCellPosition();
// if (methodExecToVertexMap.get(methodExec).getArguments().contains(objectToVertexMap.get(calledObjectId)) || methodExecToVertexMap.get(methodExec).getLocals().contains(objectToVertexMap.get(calledObjectId))) {
// calledCell.getParent().remove(calledCell);
// calledCell.setParent(mxDefaultParent);
// calledCell.getGeometry().setX(absolutePointCalledCell.getX());
// calledCell.getGeometry().setY(absolutePointCalledCell.getY());
// deltaAnimation.setVertexAnimation(calledCell, new mxPoint(objectToVertexMap.get(calledObjectId).getInitialX(), objectToVertexMap.get(calledObjectId).getInitialY()));
// deltaAnimation.startVertexAnimation();
// }
removeCalledMethodExecutionVertex(sourceVertexObject, methodExec.getCallerMethodExecution(), methodExec);
updateObjectVertices();
// removeVertexMethodExecution(sourceVertexObject, methodExec);
// update();
break;
}
}
}
} else {
outputLog();
// Change!
List<ObjectVertex> arguments = new ArrayList<>(methodExecToVertexMap.get(methodExec).getArguments());
List<ObjectVertex> locals = new ArrayList<>(methodExecToVertexMap.get(methodExec).getLocals());
if (arguments.size() != 0) {
for (ObjectVertex vo: arguments) {
mxICell cell = (mxICell)vo.getCell();
Point absolutePointCell = getAbsolutePointforCell(cell);
cell.getParent().remove(cell);
cell.setParent(mxDefaultParent);
cell.getGeometry().setX(absolutePointCell.getX());
cell.getGeometry().setY(absolutePointCell.getY());
deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY()));
deltaAnimation.startVertexAnimation();
methodExecToVertexMap.get(methodExec).getArguments().remove(vo);
}
}else if (locals.size() != 0) {
for (ObjectVertex vo: locals) {
mxICell cell = (mxICell)vo.getCell();
Point absolutePointCell = getAbsolutePointforCell(cell);
cell.getParent().remove(cell);
cell.setParent(mxDefaultParent);
cell.getGeometry().setX(absolutePointCell.getX());
cell.getGeometry().setY(absolutePointCell.getY());
deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY()));
deltaAnimation.startVertexAnimation();
methodExecToVertexMap.get(methodExec).getLocals().remove(vo);
}
}
updateObjectVertices();
}
}
} finally {
mxgraph.getModel().endUpdate();
}
update();
}
/** Create ObjectVertices. */
private void createObjectVertices(ExtractedStructure eStructure) {
while(coordinatorPoint.getX() - (150 * (eStructure.getDelta().getDstSide().size())) < 0) {
coordinatorPoint.setX(coordinatorPoint.getX() + 150);
}
// 左上(0, 0)
double xCor = coordinatorPoint.getX();
double yCor = coordinatorPoint.getY();
double time = 150;
//Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
// Draw vertex object.
// srcSide
Delta delta = eStructure.getDelta();
int srcSideSize = delta.getSrcSide().size();
for (int i = srcSideSize - 1; i >= 0; i--) {
Reference ref = delta.getSrcSide().get(i);
System.out.println("srcSide: " + ref.getSrcClassName() + ", " + ref.isCreation());
if (!ref.isCreation() && !ref.getSrcObjectId().equals(ref.getDstObjectId())) {
if (!objectToVertexMap.containsKey(ref.getSrcObjectId())) {
String srcClassName = ref.getSrcClassName();
if (srcClassName.contains("[L")) {
srcClassName = formatArrayName(srcClassName);
}
Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex.
objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i))));
}
if (!objectToVertexMap.containsKey(ref.getDstObjectId())) {
System.out.println(ref.getDstClassName() + ", " + ref.isCreation());
String dstClassName = ref.getDstClassName();
if (dstClassName.contains("[L")) {
dstClassName = formatArrayName(dstClassName);
}
Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getDstObjectId(), dstClassName, xCor + (time * (srcSideSize - i)), yCor + (time * (srcSideSize - i)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex.
objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), vertex, xCor + (time * (srcSideSize - i)), yCor + (time * (srcSideSize - i))));
}
} else {
objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), null, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i))));
}
}
// dstSide
int dstSideSize = delta.getDstSide().size();
int cnt = 0;
for (int i = dstSideSize - 1; i >= 0; i--) {
Reference ref = delta.getDstSide().get(i);
System.out.println("dstSide: " + ref.getSrcClassName() + ", " + ref.getDstClassName() + ", " + ref.isCreation());
if (!ref.isCreation() && !ref.getSrcObjectId().equals(ref.getDstObjectId())) {
if (!objectToVertexMap.containsKey(ref.getSrcObjectId())) {
String srcClassName = ref.getSrcClassName();
if (srcClassName.contains("[L")) {
srcClassName = formatArrayName(srcClassName);
}
Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex.
objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt))));
cnt++;
}
if (!objectToVertexMap.containsKey(ref.getDstObjectId())) {
String dstClassName = ref.getDstClassName();
if (dstClassName.contains("[L")) {
dstClassName = formatArrayName(dstClassName);
}
Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getDstObjectId(), dstClassName, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex.
objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), vertex, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt))));
}
} else {
objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), null, xCor - (time * (dstSideSize - i + cnt)), yCor + (time * (dstSideSize - i + cnt))));
}
}
} finally {
mxgraph.getModel().endUpdate();
}
}
/**
* Create ObjectVertex when CONSTRACTOR_INVOCATION.
* @param alias
*/
private void createObjectVertexOnConstractor(Alias alias) {
ObjectVertex vertexObj = objectToVertexMap.get(alias.getObjectId());
String souceObjId = alias.getMethodExecution().getThisObjId();
mxICell sourceCell = (mxICell)objectToVertexMap.get(souceObjId).getCell();
double sourceWidth = sourceCell.getGeometry().getWidth();
double sourceHeight = sourceCell.getGeometry().getHeight();
double overlapWidth = sourceWidth * Math.sqrt(2) * 0.1;
double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1);
MethodInvocation methodInvocation = (MethodInvocation)alias.getOccurrencePoint().getStatement();
String fieldName = methodInvocation.getCallerSideMethodName();
List<AliasPair> aliasPairListByAlias = deltaAliasCollector.getAliasPairListByAlias(alias);
AliasPair aliasPair = null;
if (aliasPairListByAlias.size() >= 1) {
aliasPair = aliasPairListByAlias.get(0);
}
boolean isSrcSideChanged = aliasPair.getIsSrcSideChanged();
Point absolutePointSourceCell = getAbsolutePointforCell(sourceCell);
mxgraph.getModel().beginUpdate();
try {
Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, vertexObj.getLabel(), vertexObj.getLabel(), absolutePointSourceCell.getX() + overlapWidth, absolutePointSourceCell.getY() + overlapHeight, VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex.
vertexObj.setCell(vertex);
Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldName, null, sourceCell, vertex);
if(isSrcSideChanged) {
((mxCell)edge).setStyle("exitX=1;exitY=1;exitPerimeter=1;entryX=0;entryY=0;entryPerimeter=1;");
} else {
((mxCell)edge).setStyle("exitX=0;exitY=1;exitPerimeter=1;entryX=1;entryY=0;entryPerimeter=1;");
}
edgeMap.put(alias.getMethodExecution().getThisClassName() + "." + fieldName, new Edge(fieldName, TypeName.Create, edge));
setCellsStyle();
deltaAnimation.setVertexAnimation((mxICell)vertex, new mxPoint(vertexObj.getInitialX(), vertexObj.getInitialY()));
deltaAnimation.startVertexAnimation();
} finally {
mxgraph.getModel().endUpdate();
}
}
private void createObjectRefrence(FieldUpdate fieldUpdateStatement, String fieldName) {
String sourceObjectId = fieldUpdateStatement.getContainerObjId();
String targetObjectId = fieldUpdateStatement.getValueObjId();
mxICell sourceCell = (mxICell)objectToVertexMap.get(sourceObjectId).getCell();
mxICell targetCell = (mxICell)objectToVertexMap.get(targetObjectId).getCell();
Point absolutePointTargetCell = getAbsolutePointforCell(targetCell);
targetCell.getParent().remove(targetCell);
targetCell.setParent(mxDefaultParent);
targetCell.getGeometry().setX(absolutePointTargetCell.getX());
targetCell.getGeometry().setY(absolutePointTargetCell.getY());
Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldUpdateStatement.getFieldName(), fieldName, objectToVertexMap.get(sourceObjectId).getCell(), objectToVertexMap.get(targetObjectId).getCell());
((mxCell)edge).setStyle("exitX=0;exitY=0.5;exitPerimeter=1;entryX=1;entryY=0.5;entryPerimeter=1;");
edgeMap.put(fieldUpdateStatement.getFieldName(), new Edge(fieldName, TypeName.Reference, edge));
// System.out.println("last" + objectToVertexMap.get(targetObjectId).getInitialX() + ", " + objectToVertexMap.get(targetObjectId).getInitialY());
deltaAnimation.setVertexAnimation(targetCell, new mxPoint(objectToVertexMap.get(targetObjectId).getInitialX(), objectToVertexMap.get(targetObjectId).getInitialY()));
deltaAnimation.startVertexAnimation();
targetCell.getGeometry().setX(objectToVertexMap.get(targetObjectId).getInitialX());
targetCell.getGeometry().setY(objectToVertexMap.get(targetObjectId).getInitialY());
}
private void createObjectRefrence(MethodExecution methodExec) {
String sourceObjectId = methodExec.getThisObjId();
String srcClassName = methodExec.getThisClassName();
String targetObjectId = methodExec.getArguments().get(0).getId();
mxICell targetCell = (mxICell)objectToVertexMap.get(targetObjectId).getCell();
Point absolutePointTargetCell = getAbsolutePointforCell(targetCell);
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
targetCell.getParent().remove(targetCell);
targetCell.setParent(mxDefaultParent);
targetCell.getGeometry().setX(absolutePointTargetCell.getX());
targetCell.getGeometry().setY(absolutePointTargetCell.getY());
Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, targetObjectId, null, objectToVertexMap.get(sourceObjectId).getCell(), objectToVertexMap.get(targetObjectId).getCell());
((mxCell)edge).setStyle("exitX=0;exitY=0.5;exitPerimeter=1;entryX=1;entryY=0.5;entryPerimeter=1;");
edgeMap.put(targetObjectId, new Edge(null, TypeName.Reference, edge));
// System.out.println("last" + objectToVertexMap.get(targetObjectId).getInitialX() + ", " + objectToVertexMap.get(targetObjectId).getInitialY());
deltaAnimation.setVertexAnimation(targetCell, new mxPoint(objectToVertexMap.get(targetObjectId).getInitialX(), objectToVertexMap.get(targetObjectId).getInitialY()));
deltaAnimation.startVertexAnimation();
targetCell.getGeometry().setX(objectToVertexMap.get(targetObjectId).getInitialX());
targetCell.getGeometry().setY(objectToVertexMap.get(targetObjectId).getInitialY());
} finally {
mxgraph.getModel().endUpdate();
}
System.out.println("rTHIS " + srcClassName + ", " + targetObjectId);
}
/**
* SourceVertex move targetVertex.
*
* @param alias
*/
private void moveObjectVertex(Alias alias) {
// sourceVertex
ObjectVertex sourceObjectVertex = objectToVertexMap.get(alias.getObjectId());
if (alias.getMethodExecution().isStatic() && !methodExecToVertexMap.containsKey(alias.getMethodExecution())) {
createMethodExecutionVertex(alias, alias.getMethodExecution().getSignature(), alias.getMethodExecution());
}
// targetVertex
MethodExecutionVertex targetMethodExecVertex = methodExecToVertexMap.get(alias.getMethodExecution());
System.out.println("moveObjectVertex: " + targetMethodExecVertex);
System.out.println("moveObjectVertex: " + alias.getMethodExecution().isStatic());
moveObjectVertex(alias, sourceObjectVertex, targetMethodExecVertex);
updateObjectVertices();
}
/**
* Parent : Source VertexObject move target VertexMethodExecution.
*
* @param alias
* @param sourceVertexObject Source VertexObject.
* @param targetVertexMethodExec Target VertexMethodExecution.
*/
private void moveObjectVertex(Alias alias, ObjectVertex sourceVertexObject, MethodExecutionVertex targetVertexMethodExec) {
MethodExecution methodExec = alias.getMethodExecution();
if (alias.getAliasType().equals(AliasType.RETURN_VALUE) || alias.getAliasType().equals(AliasType.METHOD_INVOCATION)) {
moveLocalObjectVertex(methodExec, sourceVertexObject, targetVertexMethodExec);
} else if (alias.getAliasType().equals(AliasType.FORMAL_PARAMETER)) {
moveArgumentObjectVertex(methodExec, sourceVertexObject, targetVertexMethodExec);
} else if (alias.getAliasType().equals(AliasType.ACTUAL_ARGUMENT)) {
moveActualArgumentObjectVertex(methodExec, sourceVertexObject, targetVertexMethodExec);
}
}
/**
* Source VertexObject move target VertexMethodExecution to Local position from caller MethodExecution.
*
* @param callerMethodExec Caller MethodExecution.
* @param sourceVertexObject
* @param targetVertexMethodExec
*/
private void moveLocalObjectVertex(MethodExecution callerMethodExec, ObjectVertex sourceVertexObject, MethodExecutionVertex targetVertexMethodExec) {
mxICell sourceCell = (mxICell)sourceVertexObject.getCell();
mxICell targetCell = (mxICell) targetVertexMethodExec.getCell();
if (sourceCell == targetCell.getParent()) {
System.out.println("nothing.");
return;
}
// Remove sourceVertex from Locals and Arguments Vertex of MethodExecution's Vertex.
if (methodExecToVertexMap.containsKey(callerMethodExec) && methodExecToVertexMap.get(callerMethodExec).getLocals().contains(sourceVertexObject)) {
methodExecToVertexMap.get(callerMethodExec).getLocals().remove(sourceVertexObject);
System.out.println(methodExecToVertexMap.get(callerMethodExec).getLabel() + " :removeLocal: " + sourceVertexObject.getLabel());
}
if (methodExecToVertexMap.containsKey(callerMethodExec) && methodExecToVertexMap.get(callerMethodExec).getArguments().contains(sourceVertexObject)) {
methodExecToVertexMap.get(callerMethodExec).getArguments().remove(sourceVertexObject);
System.out.println(methodExecToVertexMap.get(callerMethodExec).getLabel() + " :removeArgument: " + sourceVertexObject.getLabel());
}
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
int time = targetVertexMethodExec.getLocals().size();
double sourceX = sourceCell.getGeometry().getX();
double sourceY = sourceCell.getGeometry().getY();
// System.out.println(time);
if(sourceCell.getParent().getValue() != null) {
Point absolutePointSourceCell = getAbsolutePointforCell(sourceCell);
sourceX = absolutePointSourceCell.getX();
sourceY = absolutePointSourceCell.getY();
sourceCell.getParent().remove(sourceCell);
}
sourceCell.setParent(targetCell.getParent());
targetCell.getParent().insert(sourceCell);
System.out.println("moveLocalObjectVertex: " + sourceCell.getId() + " (" + sourceCell.hashCode() + ")" + ", " + sourceCell.getParent().getId() + " (" + sourceCell.getParent().hashCode() + ")");
System.out.println(" " + targetCell.getId() + " (" + targetCell.hashCode() + ")" + ", " + targetCell.getParent().getId() + " (" + targetCell.getParent().hashCode() + ")");
Point absolutePointTargetCell = getAbsolutePointforCell(sourceCell.getParent());
sourceCell.getGeometry().setX(sourceX - absolutePointTargetCell.getX());
sourceCell.getGeometry().setY(sourceY - absolutePointTargetCell.getY());
double sourceWidth = sourceCell.getGeometry().getWidth();
double sourceHeight = sourceCell.getGeometry().getHeight();
double targetWidth = targetCell.getGeometry().getWidth();
double targetHeight = targetCell.getGeometry().getHeight();
double overlapWidth = sourceWidth - (sourceWidth * Math.sqrt(2) * 0.1);
double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1);
// deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth, targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time)));
// deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth + (sourceWidth * time), targetCell.getGeometry().getY() - overlapHeight + sourceHeight));
deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - (sourceWidth / Math.sqrt(2.5)) + (sourceWidth * time), targetCell.getGeometry().getY() + targetHeight));
deltaAnimation.startVertexAnimation();
sourceCell.setParent(targetCell.getParent());
targetCell.getParent().insert(sourceCell);
// sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth);
// sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time));
// sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth + (sourceWidth * time));
// sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + sourceHeight);
sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - (sourceWidth / Math.sqrt(2.5)) + (sourceWidth * time));
sourceCell.getGeometry().setY(targetCell.getGeometry().getY() + targetHeight);
targetVertexMethodExec.getLocals().add(sourceVertexObject);
System.out.println("moveLocalObjectVertex: " + targetVertexMethodExec.getLabel() + " :Local: " + sourceVertexObject.getLabel());
} finally {
mxgraph.getModel().endUpdate();
}
}
/**
* Source VertexObject move target VertexMethodExecution to Argument position from MethodExecution.
*
* @param methodExec MethodExecution.
* @param sourceVertexObject move
* @param targetVertexMethodExec
*/
private void moveArgumentObjectVertex(MethodExecution methodExec, ObjectVertex sourceVertexObject, MethodExecutionVertex targetVertexMethodExec) {
mxICell sourceCell = (mxICell)sourceVertexObject.getCell();
mxICell targetCell = (mxICell) targetVertexMethodExec.getCell();
// mxICell parentTargetMethodExecCell = targetMethodExecCell.getParent();
// Remove sourceVertex from Locals and Arguments Vertex of MethodExecution's Vertex.
MethodExecution callerMethodExecution = methodExec.getCallerMethodExecution();
if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getLocals().contains(sourceVertexObject)) {
methodExecToVertexMap.get(callerMethodExecution).getLocals().remove(sourceVertexObject);
System.out.println(methodExecToVertexMap.get(callerMethodExecution).getLabel() + " :removeLocal: " + sourceVertexObject.getLabel());
}
if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getArguments().contains(sourceVertexObject)) {
methodExecToVertexMap.get(callerMethodExecution).getArguments().remove(sourceVertexObject);
System.out.println(methodExecToVertexMap.get(callerMethodExecution).getLabel() + " :removeArgument: " + sourceVertexObject.getLabel());
}
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
int time = targetVertexMethodExec.getArguments().size();
double sourceX = sourceCell.getGeometry().getX();
double sourceY = sourceCell.getGeometry().getY();
// System.out.println(time);
if(sourceCell.getParent().getValue() != null) {
Point absolutePointSourceCell = getAbsolutePointforCell(sourceCell);
sourceX = absolutePointSourceCell.getX();
sourceY = absolutePointSourceCell.getY();
sourceCell.getParent().remove(sourceCell);
}
if (!isParent(targetCell, sourceCell)) {
sourceCell.setParent(targetCell.getParent());
targetCell.getParent().insert(sourceCell);
Point absolutePointSourceParentCell = getAbsolutePointforCell(sourceCell.getParent());
sourceCell.getGeometry().setX(sourceX - absolutePointSourceParentCell.getX());
sourceCell.getGeometry().setY(sourceY - absolutePointSourceParentCell.getY());
double sourceWidth = sourceCell.getGeometry().getWidth();
double sourceHeight = sourceCell.getGeometry().getHeight();
double overlapWidth = sourceWidth - (sourceWidth * Math.sqrt(2) * 0.1);
double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1);
deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth, targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time)));
deltaAnimation.startVertexAnimation();
// sourceCell.setParent(targetCell.getParent());
// targetCell.getParent().insert(sourceCell);
sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth);
sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time));
targetVertexMethodExec.getArguments().add(sourceVertexObject);
System.out.println("moveArgumentObejctVertex" + targetVertexMethodExec.getLabel() + " :Argument: " + sourceVertexObject.getLabel());
} else { // 仕様上のバグ, ループが発生
outputLog();
// try {
// ObjectVertex(sourceCell)のクローン生成
// mxICell cloneSourceCell = (mxICell) mxgraph.addCell(sourceCell.clone());
//
// cloneSourceCell.setStyle("fillColor=#ffffff;opacity=50;shape=ellipse");
// cloneSourceCell.setId("clone" + cloneSourceCell.getId());
// cloneSourceCell.setValue(null);
// cloneSourceCell.setParent(sourceCell);
// sourceCell.insert(cloneSourceCell);
// cloneSourceCell.getGeometry().setX(0);
// cloneSourceCell.getGeometry().setX(0);
// cloneSourceCell.getGeometry().setY(0);
// 元のObjectVertex
Point absPtSourceCell = getAbsolutePointforCell(sourceCell);
Point absPtTargetParentCell = getAbsolutePointforCell(targetCell.getParent());
sourceCell.remove(targetCell.getParent());
targetCell.getParent().setParent(mxDefaultParent);
sourceCell.setParent(targetCell.getParent());
targetCell.getParent().insert(sourceCell);
targetCell.getParent().getGeometry().setX(absPtTargetParentCell.getX());
targetCell.getParent().getGeometry().setY(absPtTargetParentCell.getY());
sourceCell.getGeometry().setX(absPtSourceCell.getX() - absPtTargetParentCell.getX());
sourceCell.getGeometry().setY(absPtSourceCell.getY() - absPtTargetParentCell.getY());
sourceCell.setStyle("opacity=50;shape=ellipse");
double sourceWidth = sourceCell.getGeometry().getWidth();
double sourceHeight = sourceCell.getGeometry().getHeight();
// double overlapWidth = targetCell.getGeometry().getWidth() / 2;
double overlapWidth = sourceWidth - (sourceWidth * Math.sqrt(2) * 0.1);
double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1);
// deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() + overlapWidth, targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time)));
deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth + (sourceWidth * time), targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time)));
deltaAnimation.startVertexAnimation();
outputLog();
// sourceCell.getGeometry().setX(targetCell.getGeometry().getX() + overlapWidth);
sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth + (sourceWidth * time));
sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time));
targetVertexMethodExec.getArguments().add(sourceVertexObject);
// } catch (CloneNotSupportedException e) {
// e.printStackTrace();
// }
}
} finally {
mxgraph.getModel().endUpdate();
}
}
/**
* Source VertexObject move target VertexMethodExecution to Argument position from MethodExecution.
*
* @param methodExec MethodExecution.
* @param sourceVertexObject
* @param targetVertexMethodExec
*/
private void moveActualArgumentObjectVertex(MethodExecution methodExec, ObjectVertex sourceVertexObject, MethodExecutionVertex targetVertexMethodExec) {
mxICell sourceCell = (mxICell)sourceVertexObject.getCell();
mxICell targetCell = (mxICell) targetVertexMethodExec.getCell();
// mxICell parentTargetMethodExecCell = targetMethodExecCell.getParent();
if (sourceCell == targetCell.getParent()) {
System.out.println("nothing.");
return;
}
// Remove sourceVertex from Locals and Arguments Vertex of MethodExecution's Vertex.
// MethodExecution callerMethodExecution = methodExec.getCallerMethodExecution();
System.out.println(methodExec.getSignature());
System.out.println(sourceVertexObject.getLabel());
// if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getLocals().contains(sourceVertexObject)) {
// methodExecToVertexMap.get(callerMethodExecution).getLocals().remove(sourceVertexObject);
// System.out.println(methodExecToVertexMap.get(callerMethodExecution).getLabel() + " :removeLocal: " + sourceVertexObject.getLabel());
// }
//
// if (methodExecToVertexMap.containsKey(callerMethodExecution) && methodExecToVertexMap.get(callerMethodExecution).getArguments().contains(sourceVertexObject)) {
// methodExecToVertexMap.get(callerMethodExecution).getArguments().remove(sourceVertexObject);
// System.out.println(methodExecToVertexMap.get(callerMethodExecution).getLabel() + " :removeArgument: " + sourceVertexObject.getLabel());
// }
if (methodExecToVertexMap.containsKey(methodExec) && methodExecToVertexMap.get(methodExec).getLocals().contains(sourceVertexObject)) {
methodExecToVertexMap.get(methodExec).getLocals().remove(sourceVertexObject);
System.out.println(methodExecToVertexMap.get(methodExec).getLabel() + " :removeLocal: " + sourceVertexObject.getLabel());
}
if (methodExecToVertexMap.containsKey(methodExec) && methodExecToVertexMap.get(methodExec).getArguments().contains(sourceVertexObject)) {
methodExecToVertexMap.get(methodExec).getArguments().remove(sourceVertexObject);
System.out.println(methodExecToVertexMap.get(methodExec).getLabel() + " :removeArgument: " + sourceVertexObject.getLabel());
}
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
// int time = targetVertexMethodExec.getArguments().size();
// int time = targetVertexMethodExec.getLocals().size() + 1;
int time = targetVertexMethodExec.getLocals().size();
double sourceX = sourceCell.getGeometry().getX();
double sourceY = sourceCell.getGeometry().getY();
System.out.println(time + ", " + targetVertexMethodExec.getLocals().size());
// if (time == 0) time = 1;
if(sourceCell.getParent().getValue() != null) {
Point absolutePointSourceCell = getAbsolutePointforCell(sourceCell);
sourceX = absolutePointSourceCell.getX();
sourceY = absolutePointSourceCell.getY();
sourceCell.getParent().remove(sourceCell);
}
sourceCell.setParent(targetCell.getParent());
targetCell.getParent().insert(sourceCell);
Point absolutePointSourceParentCell = getAbsolutePointforCell(sourceCell.getParent());
sourceCell.getGeometry().setX(sourceX - absolutePointSourceParentCell.getX());
sourceCell.getGeometry().setY(sourceY - absolutePointSourceParentCell.getY());
double sourceWidth = sourceCell.getGeometry().getWidth();
double sourceHeight = sourceCell.getGeometry().getHeight();
double targetWidth = targetCell.getGeometry().getWidth();
double targetHeight = targetCell.getGeometry().getHeight();
double overlapWidth = sourceWidth - (sourceWidth * Math.sqrt(2) * 0.1);
double overlapHeight = sourceHeight - (sourceHeight * Math.sqrt(2) * 0.1);
// deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - overlapWidth, targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time)));
deltaAnimation.setVertexAnimation(sourceCell, new mxPoint(targetCell.getGeometry().getX() - (sourceWidth / Math.sqrt(3)) + (sourceWidth * time), targetCell.getGeometry().getY() + targetHeight));
deltaAnimation.startVertexAnimation();
// sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth);
// sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time));
sourceCell.getGeometry().setX(targetCell.getGeometry().getX() - (sourceWidth / Math.sqrt(3)) + (sourceWidth * time));
sourceCell.getGeometry().setY(targetCell.getGeometry().getY() + targetHeight);
targetVertexMethodExec.getArguments().add(sourceVertexObject);
System.out.println("moveActualArgumentObjectVertex: " + targetVertexMethodExec.getLabel() + " :Argument: " + sourceVertexObject.getLabel());
} finally {
mxgraph.getModel().endUpdate();
}
}
// private void moveInitialObjectVertex(MethodExecution methodExecution) {
// for(Statement statement: methodExecution.getStatements()) {
// if(statement instanceof MethodInvocation) {
// // moveInitialVertexObject((MethodInvocation) statement);
// MethodExecution calledMethodExec = ((MethodInvocation)statement).getCalledMethodExecution();
// String calledObjectId = calledMethodExec.getThisObjId();
// mxICell calledCell = (mxICell)objectToVertexMap.get(calledObjectId).getCell();
// Point absolutePointCalledCell = getAbsolutePointforCell(calledCell);
// // System.out.println(objectId + ", " + methodExec.getSignature());
// // objectToVertexMap.get(calledObjectId).resetCellPosition();
// if (methodExecToVertexMap.get(methodExecution).getArguments().contains(objectToVertexMap.get(calledObjectId)) || methodExecToVertexMap.get(methodExecution).getLocals().contains(objectToVertexMap.get(calledObjectId))) {
// calledCell.getParent().remove(calledCell);
// calledCell.setParent(mxDefaultParent);
// calledCell.getGeometry().setX(absolutePointCalledCell.getX());
// calledCell.getGeometry().setY(absolutePointCalledCell.getY());
// deltaAnimation.setVertexAnimation(calledCell, new mxPoint(objectToVertexMap.get(calledObjectId).getInitialX(), objectToVertexMap.get(calledObjectId).getInitialY()));
// deltaAnimation.startVertexAnimation();
// break;
// }
// }
// }
// }
/** Update ObjectVertices size and position. */
private void updateObjectVertices() {
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology
mxgraph.getModel().beginUpdate();
try {
for (ObjectVertex objectVertex: objectToVertexMap.values()) {
mxCell objectVertexCell = ((mxCell) objectVertex.getCell());
if (objectVertexCell != null) {
int time = 0;
for (int i = 0; i < objectVertexCell.getChildCount(); i++) {
if (!(objectVertexCell.getChildAt(i).getId()).contains("clone")) {
time++;
}
}
if (time == 0) {
time = 1;
}
if(objectVertexCell.getGeometry().getWidth() != VERTEX_OBJECT_SIZE.getWidth() * time) {
System.out.println("updateVertexObjectSize: " + objectVertexCell.getGeometry().getWidth() + "->" + VERTEX_OBJECT_SIZE.getWidth() * time+ ", " + objectVertexCell.getId());
Dimension targetDimension = new Dimension();
targetDimension.setSize(VERTEX_OBJECT_SIZE.getWidth() * time, VERTEX_OBJECT_SIZE.getHeight() * time);
if (objectVertexCell.getParent() != mxDefaultParent && (objectVertexCell.getChildCount() != 0 || objectVertexCell.getGeometry().getWidth() > VERTEX_OBJECT_SIZE.getWidth() * time)) {
double overlapX = (targetDimension.getWidth() - objectVertexCell.getGeometry().getWidth()) / 2 / Math.sqrt(2);
double overlapY = (targetDimension.getHeight() - objectVertexCell.getGeometry().getHeight()) / 2 / Math.sqrt(2);
System.out.println("updateVertexObjectPosition: " + objectVertexCell.getGeometry().getX() + " - " + overlapX);
mxPoint targetPoint = new mxPoint(objectVertexCell.getGeometry().getX() - overlapX, objectVertexCell.getGeometry().getY() + overlapY);
for (MethodExecutionVertex methodExecVertex: methodExecToVertexMap.values()) {
List<ObjectVertex> arguments = methodExecVertex.getArguments();
if (arguments != null && arguments.contains(objectVertex)) {
targetPoint.setY(objectVertexCell.getGeometry().getY() - overlapY);
break;
}
}
deltaAnimation.setVertexAnimation(objectVertexCell, targetPoint);
deltaAnimation.startVertexAnimation();
}
deltaAnimation.setResizeVertexAnimation(objectVertexCell, targetDimension);
deltaAnimation.startResizeVertexAnimation();
}
}
}
} finally {
mxgraph.getModel().endUpdate();
}
}
/**
* Update VertexObject of targetMethodExecCell size have sourceObjectCell.
*
* @param sourceObjectCell
* @param targetMethodExecCell
*/
// private void updateVertexObjectSize(mxICell sourceObjectCell, mxICell targetMethodExecCell) {
// mxICell parentTargetMethodExecCell = targetMethodExecCell.getParent();
//
// //Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
// mxgraph.getModel().beginUpdate();
// try {
// double preX = parentTargetMethodExecCell.getGeometry().getX();
// double preY = parentTargetMethodExecCell.getGeometry().getY();
// double preCenterX = parentTargetMethodExecCell.getGeometry().getCenterX();
// double preCenterY = parentTargetMethodExecCell.getGeometry().getCenterY();
// parentTargetMethodExecCell.getGeometry().setWidth(parentTargetMethodExecCell.getGeometry().getWidth() * 1.8);
// parentTargetMethodExecCell.getGeometry().setHeight(parentTargetMethodExecCell.getGeometry().getHeight() * 1.8);
// parentTargetMethodExecCell.getGeometry().setX(preX - (parentTargetMethodExecCell.getGeometry().getCenterX() - preCenterX));
// parentTargetMethodExecCell.getGeometry().setY(preY - (parentTargetMethodExecCell.getGeometry().getCenterY() - preCenterY));
// } finally {
// mxgraph.getModel().endUpdate();
// }
// }
/**
* Create MethodExecutionVertex.
*
* @param alias
*/
private void createMethodExecutionVertex(Alias alias) {
if (curFrame == 0) {
createMethodExecutionVertex(alias, alias.getMethodExecution().getSignature(), alias.getMethodExecution());
} else if (alias.getObjectId().matches("0")) {
createMethodExecutionVertex(alias, alias.getMethodExecution().getSignature(), alias.getMethodExecution());
}
}
/**
* Parent : Create MethodExecutionVertex.
*
* @param alias
* @param methodSignature Called or this MethodSignature.
* @param methodExec Called or this MethodExecution.
*/
private void createMethodExecutionVertex(Alias alias, String methodSignature, MethodExecution methodExec) {
if (methodSignature.contains(" ")) {
System.out.println(methodSignature);
methodSignature = formatMethodSignature(methodSignature);
}
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
String objectId = alias.getObjectId();
if (methodExec.isStatic() && !objectId.equals("0")) {
objectId = alias.getMethodExecution().getCallerMethodExecution().getThisObjId();
}
Object object = objectToVertexMap.get(objectId).getCell();
double xCor = VERTEX_OBJECT_SIZE.getWidth() * 0.1;
double yCor = VERTEX_OBJECT_SIZE.getHeight() * 0.5;
double standardX = xCor;
double standardY = 0;
int time = objectToVertexMap.get(objectId).getVertexMethodExecutions().size();
System.out.println(time);
if (time >= 1) {
mxICell standardCell = (mxICell) objectToVertexMap.get(objectId).getVertexMethodExecutions().get(0).getCell();
standardX = standardCell.getGeometry().getX();
standardY = standardCell.getGeometry().getY();
time-=1;
}
Object vertex = mxgraph.insertDeltaVertex(object, methodSignature, methodSignature, "fillColor=white"); //creates a white vertex.
System.out.println("makeVertexMethodExecution: " + ((mxICell)vertex).getId() + " in " + objectId + " (" + standardX + ", " + yCor * (time + 1) + standardY + ")");
MethodExecutionVertex vertexMethodExecution = new MethodExecutionVertex(methodSignature, vertex, standardX , yCor * (time + 1) + standardY, VERTEX_METHOD_EXECUTION_SIZE.getWidth(), VERTEX_METHOD_EXECUTION_SIZE.getHeight());
// Object vertex = mxgraph.insertVertex(object, methodSignature, methodSignature, 0, 0, 0, 0, "fillColor=white", true); //creates a white vertex.
// Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, methodSignature, methodSignature, "fillColor=white"); //creates a white vertex.
// VertexMethodExecution vertexMethodExecution = new VertexMethodExecution(methodSignature, vertex, getXForCell(objectId) + (xCor * (time + 1)), getYForCell(objectId) + (yCor * (time + 1)), VERTEX_METHOD_EXECUTION_SIZE.getWidth(), VERTEX_METHOD_EXECUTION_SIZE.getHeight());
methodExecToVertexMap.put(methodExec, vertexMethodExecution);
if(methodExecToVertexMap.size() > 1) {
((mxICell)vertex).setVisible(false);
createEdgeToMethodExecution();
}
objectToVertexMap.get(objectId).addMethodExecution(vertexMethodExecution);
} finally {
mxgraph.getModel().endUpdate();
}
setCellsStyle();
}
/**
* Remove VertexMethodExecution on AliasType is MethodInvocation of alias.
*
* @param alias
*/
private void removeMethodExecutionVertex(Alias alias) {
// sourceVertex
ObjectVertex sourceVertexObject = objectToVertexMap.get(alias.getObjectId());
MethodExecution methodExec = alias.getMethodExecution();
if(alias.getAliasType().equals(AliasType.METHOD_INVOCATION) || alias.getAliasType().equals(AliasType.CONSTRACTOR_INVOCATION)) {
MethodExecution calledMethodExec = ((MethodInvocation) alias.getOccurrencePoint().getStatement()).getCalledMethodExecution();
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
List<ObjectVertex> arguments = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getArguments());
List<ObjectVertex> locals = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getLocals());
if (arguments.size() != 0) {
for (ObjectVertex vo: arguments) {
if (vo != sourceVertexObject) {
System.out.println("argumentRemove");
mxICell cell = (mxICell)vo.getCell();
Point absolutePointCell = getAbsolutePointforCell(cell);
cell.getParent().remove(cell);
cell.setParent(mxDefaultParent);
cell.getGeometry().setX(absolutePointCell.getX());
cell.getGeometry().setY(absolutePointCell.getY());
deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY()));
deltaAnimation.startVertexAnimation();
methodExecToVertexMap.get(calledMethodExec).getArguments().remove(vo);
}
}
}
if (locals.size() != 0) {
for (ObjectVertex vo: locals) {
if (vo != sourceVertexObject) {
System.out.println("localRemove");
mxICell cell = (mxICell)vo.getCell();
Point absolutePointCell = getAbsolutePointforCell(cell);
cell.getParent().remove(cell);
cell.setParent(mxDefaultParent);
cell.getGeometry().setX(absolutePointCell.getX());
cell.getGeometry().setY(absolutePointCell.getY());
deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY()));
deltaAnimation.startVertexAnimation();
methodExecToVertexMap.get(calledMethodExec).getLocals().remove(vo);
}
}
}
} finally {
mxgraph.getModel().endUpdate();
}
removeCalledMethodExecutionVertex(sourceVertexObject, methodExec, calledMethodExec);
} else {
removeMethodExecutionVertex(sourceVertexObject, methodExec);
}
}
/**
* Remove VertexMethodExecution on AliasType is MethodInvocation of alias.
*
* @param sourceVertexObject
* @param methodExec
*/
private void removeMethodExecutionVertex(ObjectVertex sourceVertexObject, MethodExecution methodExec) {
// Remove sourceVertex from Locals and Arguments Vertex of CalledMethodExecution's Vertex.
if (methodExecToVertexMap.containsKey(methodExec)) {
mxCell targetVertexCell = (mxCell)methodExecToVertexMap.get(methodExec).getCell();
targetVertexCell.getParent().remove(targetVertexCell);
targetVertexCell.setParent(mxDefaultParent);
mxgraph.removeCells(new Object[] {targetVertexCell});
objectToVertexMap.get(methodExec.getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(methodExec));
methodExecToVertexMap.remove(methodExec);
edgeMap.remove(methodExec.getSignature());
updateObjectVertices();
}
}
/**
* Remove CalledVertexMethodExecution on AliasType is MethodInvocation of alias.
*
* @param sourceVertexObject
* @param methodExec
* @param calledMethodExec
*/
private void removeCalledMethodExecutionVertex(ObjectVertex sourceVertexObject, MethodExecution methodExec, MethodExecution calledMethodExec) {
outputLog();
// Remove sourceVertex from Locals and Arguments Vertex of CalledMethodExecution's Vertex.
if (methodExecToVertexMap.containsKey(calledMethodExec)) {
mxICell sourceVertexCell = (mxICell)methodExecToVertexMap.get(methodExec).getCell();
mxCell targetVertexCell = (mxCell)methodExecToVertexMap.get(calledMethodExec).getCell();
if(!calledMethodExec.isStatic()) {
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
// Dangerous
List<ObjectVertex> arguments = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getArguments());
List<ObjectVertex> locals = new ArrayList<>(methodExecToVertexMap.get(calledMethodExec).getLocals());
if (arguments.size() != 0) {
for (ObjectVertex vo: arguments) {
if (vo != sourceVertexObject) {
mxICell cell = (mxICell)vo.getCell();
Point absolutePointCell = getAbsolutePointforCell(cell);
System.out.println(cell);
System.out.println(vo.getInitialX() + ", " + vo.getInitialY());
System.out.println(cell.getGeometry().getX() + ", " + cell.getGeometry().getY());
System.out.println(absolutePointCell);
if (cell.getParent() != mxDefaultParent) {
cell.getParent().remove(cell);
cell.setParent(mxDefaultParent);
}
if (!absolutePointCell.equals(vo.getInitialPoint())) {
cell.getGeometry().setX(absolutePointCell.getX());
cell.getGeometry().setY(absolutePointCell.getY());
deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY()));
deltaAnimation.startVertexAnimation();
}
methodExecToVertexMap.get(calledMethodExec).getArguments().remove(vo);
}
}
}
if (locals.size() != 0) {
for (ObjectVertex vo: locals) {
if (vo != sourceVertexObject) {
mxICell cell = (mxICell)vo.getCell();
Point absolutePointCell = getAbsolutePointforCell(cell);
System.out.println(cell);
System.out.println(vo.getInitialX() + ", " + vo.getInitialY());
System.out.println(cell.getGeometry().getX() + ", " + cell.getGeometry().getY());
System.out.println(absolutePointCell);
if (cell.getParent() != mxDefaultParent) {
cell.getParent().remove(cell);
cell.setParent(mxDefaultParent);
}
if (!absolutePointCell.equals(vo.getInitialPoint())) {
cell.getGeometry().setX(absolutePointCell.getX());
cell.getGeometry().setY(absolutePointCell.getY());
deltaAnimation.setVertexAnimation(cell, new mxPoint(vo.getInitialX(), vo.getInitialY()));
deltaAnimation.startVertexAnimation();
}
methodExecToVertexMap.get(calledMethodExec).getLocals().remove(vo);
}
}
}
mxgraph.removeCells(mxgraph.getEdgesBetween(sourceVertexCell, targetVertexCell));
try {
mxICell cloneTargetVertexCell = (mxICell) mxgraph.addCell(targetVertexCell.clone());
Point absolutPointSourceVertexCell = getAbsolutePointforCell(sourceVertexCell);
Point absolutPointTargetVertexCell = getAbsolutePointforCell(targetVertexCell);
cloneTargetVertexCell.getGeometry().setX(absolutPointTargetVertexCell.getX());
cloneTargetVertexCell.getGeometry().setY(absolutPointTargetVertexCell.getY());
cloneTargetVertexCell.setStyle("fillColor=none;strokeColor=none;fontColor=#008000;");
cloneTargetVertexCell.setValue(null);
Object tempEdge = mxgraph.insertEdge(mxDefaultParent, null, null, sourceVertexCell, cloneTargetVertexCell);
((mxCell)tempEdge).setStyle("dashed=1;strokeColor=#008000;exitX=0.5;exitY=1;exitPerimeter=1;entryX=0.5;entryY=0;entryPerimeter=1;endArrow=none");
deltaAnimation.setReductionEdgeAnimation(cloneTargetVertexCell, new mxPoint(absolutPointSourceVertexCell.getX(), absolutPointSourceVertexCell.getY() + sourceVertexCell.getGeometry().getHeight()));
deltaAnimation.startReductionEdgeAnimation();
// deltaAnimation.setReductionEdgeAnimation(new mxPoint(absolutPointSourceVertexCell.getX() + (sourceVertexCell.getGeometry().getWidth() / 2), absolutPointSourceVertexCell.getY() + sourceVertexCell.getGeometry().getHeight()), new mxPoint(absolutPointTargetVertexCell.getX() + (targetVertexCell.getGeometry().getWidth() / 2), absolutPointTargetVertexCell.getY()));
// deltaAnimation.startReductionEdgeAnimation();
mxgraph.removeCells(new Object[]{cloneTargetVertexCell});
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
} finally {
mxgraph.getModel().endUpdate();
}
((mxCell)targetVertexCell.getParent()).remove(targetVertexCell);
targetVertexCell.setParent(mxDefaultParent);
mxgraph.removeCells(new Object[] {targetVertexCell});
objectToVertexMap.get(calledMethodExec.getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExec));
methodExecToVertexMap.get(calledMethodExec).getLocals().remove(sourceVertexObject);
methodExecToVertexMap.remove(calledMethodExec);
edgeMap.remove(methodExec.getSignature());
// moveInitialVertexObject(methodExec);
// updateObjectVerticesSize();
} else {
((mxCell)targetVertexCell.getParent()).remove(targetVertexCell);
targetVertexCell.setParent(mxDefaultParent);
mxgraph.removeCells(new Object[] {targetVertexCell});
objectToVertexMap.get(calledMethodExec.getCallerMethodExecution().getThisObjId()).getVertexMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExec));
methodExecToVertexMap.get(calledMethodExec).getLocals().remove(sourceVertexObject);
methodExecToVertexMap.remove(calledMethodExec);
}
}
outputLog();
}
/**
* Update VertexObject of targetMethodExecCell size have sourceObjectCell.
*
* @param sourceObjectCell
* @param targetMethodExecCell
*/
// private void updateVertexObjectSize(mxICell sourceObjectCell, mxICell targetMethodExecCell) {
// mxICell parentTargetMethodExecCell = targetMethodExecCell.getParent();
//
// //Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
// mxgraph.getModel().beginUpdate();
// try {
// double preX = parentTargetMethodExecCell.getGeometry().getX();
// double preY = parentTargetMethodExecCell.getGeometry().getY();
// double preCenterX = parentTargetMethodExecCell.getGeometry().getCenterX();
// double preCenterY = parentTargetMethodExecCell.getGeometry().getCenterY();
// parentTargetMethodExecCell.getGeometry().setWidth(parentTargetMethodExecCell.getGeometry().getWidth() * 1.8);
// parentTargetMethodExecCell.getGeometry().setHeight(parentTargetMethodExecCell.getGeometry().getHeight() * 1.8);
// parentTargetMethodExecCell.getGeometry().setX(preX - (parentTargetMethodExecCell.getGeometry().getCenterX() - preCenterX));
// parentTargetMethodExecCell.getGeometry().setY(preY - (parentTargetMethodExecCell.getGeometry().getCenterY() - preCenterY));
// } finally {
// mxgraph.getModel().endUpdate();
// }
// }
/** Make edge object in JGraphT and draw this in JGraphX.
* @param map
* @param collection */
private void createEdgeToObject(List<Alias> aliasList, List<AliasPair> aliasPairList) {
for (int i = 0; i < aliasList.size()-1; i++) {
Alias curAlias = aliasList.get(i);
Alias nextAlias = aliasList.get(i+1);
String srcClassName = null;
String fieldName = null;
if (curAlias.getAliasType().equals(AliasType.THIS) /*&& nextAlias.getAliasType().equals(AliasType.FIELD)*/) {
if (nextAlias.getAliasType().equals(AliasType.RETURN_VALUE)) {
MethodExecution nextMethodExec = nextAlias.getMethodExecution();
//ArrayやListのときだけラベルを付ける(確実に分かっているものとき)getSignature->contains("List.get(") || "Map.get(") <ホワイトリスト>
if (nextMethodExec.getSignature().contains("List.get(") ||
nextMethodExec.getSignature().contains("Map.get(")) {
srcClassName = nextMethodExec.getThisClassName();
fieldName = nextMethodExec.getArguments().get(0).getId();
System.out.println("rTHIS " + srcClassName + ", " +nextMethodExec.getArguments().get(0).getId());
}
} else {
Statement statement = nextAlias.getOccurrencePoint().getStatement();
if(statement instanceof FieldAccess) {
String fieldNames[] = formatFieldName(((FieldAccess)statement).getFieldName());
srcClassName = fieldNames[0];
fieldName = fieldNames[1];
}
}
System.out.println("THIS " + srcClassName + "(" + curAlias.getObjectId() + ") -> " + "(" + nextAlias.getObjectId() + "), "+ fieldName);
}
if(curAlias.getAliasType().equals(AliasType.ARRAY)) {
Statement statement= nextAlias.getOccurrencePoint().getStatement();
if(statement instanceof ArrayAccess) {
srcClassName = ((ArrayAccess)statement).getArrayClassName();
int index = ((ArrayAccess)statement).getIndex();
fieldName = formatArrayIndex(index);
System.out.println("ARRAY " + srcClassName + "(" + curAlias.getObjectId() + ") -> " + "(" + nextAlias.getObjectId() + "), " + fieldName);
}
}
if (srcClassName != null && fieldName != null && srcClassName != null && !edgeMap.containsKey(srcClassName + "." + fieldName)) {
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
mxgraph.getModel().beginUpdate();
try {
List<AliasPair> aliasPairListByAlias = deltaAliasCollector.getAliasPairListByAliasPair(curAlias, nextAlias);
AliasPair aliasPair = null;
if (aliasPairListByAlias.size() >= 1) {
aliasPair = aliasPairListByAlias.get(0);
}
String srcObjId = aliasPair.getAliasPair().getKey().getObjectId();
String dstObjId = aliasPair.getAliasPair().getValue().getObjectId();
boolean isSrcSideChanged = aliasPair.getIsSrcSideChanged();
// String dstClassName = curAlias.getMethodExecution().getThisClassName();
System.out.println("makeEdgeObject: " + fieldName + ", " + srcClassName + " (" + objectToVertexMap.get(srcObjId).getCell().hashCode() + "), " + " (" + objectToVertexMap.get(dstObjId).getCell().hashCode() + ")"/* + ", " + dstClassName*/);
// BUG:NullPointerException
Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldName, fieldName, objectToVertexMap.get(srcObjId).getCell(), objectToVertexMap.get(dstObjId).getCell());
if(isSrcSideChanged) {
((mxCell)edge).setStyle("exitX=1;exitY=1;exitPerimeter=1;entryX=0;entryY=0;entryPerimeter=1;");
} else {
((mxCell)edge).setStyle("exitX=0;exitY=1;exitPerimeter=1;entryX=1;entryY=0;entryPerimeter=1;");
}
edgeMap.put(srcClassName + "." + fieldName, new Edge(fieldName, TypeName.Reference, edge));
} finally {
mxgraph.getModel().endUpdate();
}
}
}
}
/** Make EdgeMethodExecution. */
private void createEdgeToMethodExecution() {
List<MethodExecution> methodExecList = new ArrayList<>(methodExecToVertexMap.keySet());
// BUG : Edge Orientation Reverse.
for (int i = 0; i < methodExecList.size() - 1; i++) {
MethodExecution sourceMethodExec = methodExecList.get(i);
MethodExecution targetMethodExec = methodExecList.get(i + 1);
String methodSignature = sourceMethodExec.getSignature();
if (!edgeMap.containsKey(methodSignature)) {
mxICell sourceVertexCell = (mxICell)methodExecToVertexMap.get(sourceMethodExec).getCell();
mxICell targetVertexCell = (mxICell)methodExecToVertexMap.get(targetMethodExec).getCell();
if (!targetMethodExec.isStatic()) {
Point absolutPointSourceVertexCell = getAbsolutePointforCell(sourceVertexCell);
Point absolutPointTargetVertexCell = getAbsolutePointforCell(targetVertexCell);
// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology
mxgraph.getModel().beginUpdate();
try {
try {
mxICell cloneTargetVertexCell = (mxICell) mxgraph.addCell(targetVertexCell.clone());
cloneTargetVertexCell.getGeometry().setX(absolutPointSourceVertexCell.getX());
cloneTargetVertexCell.getGeometry().setY(absolutPointSourceVertexCell.getY() + targetVertexCell.getGeometry().getHeight());
cloneTargetVertexCell.setStyle("fillColor=none;strokeColor=none;fontColor=#008000;");
cloneTargetVertexCell.setValue(null);
cloneTargetVertexCell.setVisible(true);
Object tempEdge = mxgraph.insertEdge(mxDefaultParent, null, null, sourceVertexCell, cloneTargetVertexCell);
((mxCell)tempEdge).setStyle("dashed=1;strokeColor=#008000;exitX=0.5;exitY=1;exitPerimeter=1;entryX=0.5;entryY=0;entryPerimeter=1;endArrow=none");
deltaAnimation.setExpandEdgeAnimation(cloneTargetVertexCell, new mxPoint(absolutPointTargetVertexCell.getX(), absolutPointTargetVertexCell.getY()));
deltaAnimation.startExpandEdgeAnimation();
targetVertexCell.setVisible(true);
// deltaAnimation.setExpandEdgeAnimation(new mxPoint(absolutPointSourceVertexCell.getX() + (sourceVertexCell.getGeometry().getWidth() / 2), absolutPointSourceVertexCell.getY() + sourceVertexCell.getGeometry().getHeight()), new mxPoint(absolutPointTargetVertexCell.getX() + (targetVertexCell.getGeometry().getWidth() / 2), absolutPointTargetVertexCell.getY()));
// deltaAnimation.startExpandEdgeAnimation();
Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, methodSignature, null, sourceVertexCell, targetVertexCell);
((mxCell)edge).setStyle("exitX=0.5;exitY=1;exitPerimeter=1;entryX=0.5;entryY=0;entryPerimeter=1;");
mxgraph.removeCells(new Object[]{cloneTargetVertexCell});
edgeMap.put(methodSignature, new Edge(methodSignature, TypeName.Call, edge));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
} finally {
mxgraph.getModel().endUpdate();
}
} else {
targetVertexCell.setVisible(true);
}
}
}
}
private int countChildVertex(ObjectVertex vertexObject) {
int time = vertexObject.getVertexMethodExecutions().size();
if(time == 0) {
return 1;
}
for(MethodExecutionVertex vertexMethodExecution: vertexObject.getVertexMethodExecutions()) {
for(ObjectVertex vo: vertexMethodExecution.getLocals()) {
time += countChildVertex(vo);
}
for(ObjectVertex vo: vertexMethodExecution.getArguments()) {
return countChildVertex(vo);
}
}
System.out.println(vertexObject.getLabel() + ": " + time);
return time;
}
private String[] formatFieldName(String fieldName) {
String fieldNames[] = fieldName.split("\\.");
String names[] = new String[] {fieldNames[0], fieldNames[fieldNames.length - 1]};
for(int i = 1; i < fieldNames.length - 1; i++) {
names[0] += "." + fieldNames[i];
}
return names;
}
private String formatMethodSignature(String methodSignature) {
// Step1 : split "("
String[] methodSignatures = methodSignature.split("\\(");
methodSignature = methodSignatures[0];
// Step2 : split " "
methodSignatures = methodSignature.split(" ");
StringBuffer sb = new StringBuffer();
sb.append(methodSignatures[methodSignatures.length-1]);
sb.append("()");
return sb.toString();
}
private String formatArrayName(String srcClassName) {
// Step1 : remove "[L"
StringBuffer sb = new StringBuffer();
sb.append(srcClassName.substring(2, srcClassName.length()-1));
sb.append("[]");
return sb.toString();
}
private String formatArrayIndex(int index) {
StringBuffer sb = new StringBuffer();
sb.append("[");
sb.append(index);
sb.append("]");
return sb.toString();
}
private void outputLog() {
for (Object object: mxgraph.getChildCells(mxDefaultParent)) {
System.out.println(object + " " + object.hashCode());
for (int i = 0; i < ((mxICell)object).getChildCount(); i++) {
System.out.println(" " + ((mxICell)object).getChildAt(i) + " " + object.hashCode());
}
}
System.out.println("\nObject");
for (Entry<String, ObjectVertex> e: objectToVertexMap.entrySet()) {
String objId = e.getKey();
ObjectVertex vo = e.getValue();
if (vo.getCell() != null) {
System.out.println(vo.getLabel() + " (" + objId + ")" + " " + vo.getCell().hashCode());
} else {
System.out.println(vo.getLabel() + " (" + objId + ")");
}
for (MethodExecutionVertex vme: vo.getVertexMethodExecutions()) {
System.out.println(" " + vme.getLabel());
for (ObjectVertex vmevo: vme.getArguments()) {
System.out.println(" Argument: " + vmevo.getLabel());
}
for (ObjectVertex vmevo: vme.getLocals()) {
System.out.println(" Local: " + vmevo.getLabel());
}
}
}
System.out.println("\nEdge");
for (Edge e: edgeMap.values()) {
System.out.println(e.getLabel());
System.out.println(" " + ((mxICell)e.getCell()).getParent().getId());
}
}
private class CurvedCanvas extends mxInteractiveCanvas {
mxIShape shape = new CurvedConnector();
public CurvedCanvas(mxGraphComponent mxGraphComponent) {
super(mxGraphComponent);
}
public Object drawCell(mxCellState state) {
if (!(state.getCell() instanceof mxCell) || !((mxCell)state.getCell()).isEdge() || state.getAbsolutePointCount() == 2) {
return super.drawCell(state);
}
Map<String, Object> style = state.getStyle();
if (g != null) {
// Creates a temporary graphics instance for drawing this shape
float opacity = mxUtils.getFloat(style, mxConstants.STYLE_OPACITY, 100);
Graphics2D previousGraphics = g;
g = createTemporaryGraphics(style, opacity, state);
shape.paintShape(this, state);
g.dispose();
g = previousGraphics;
}
return shape;
}
}
private class CurvedConnector extends mxConnectorShape {
public void paintShape(mxGraphics2DCanvas canvas, mxCellState state) {
if (state.getAbsolutePointCount() > 1
&& configureGraphics(canvas, state, false)) {
List<mxPoint> pts = new ArrayList<mxPoint>(
state.getAbsolutePoints());
Map<String, Object> style = state.getStyle();
// Paints the markers and updates the points
// Switch off any dash pattern for markers
boolean dashed = mxUtils.isTrue(style, mxConstants.STYLE_DASHED);
Object dashedValue = style.get(mxConstants.STYLE_DASHED);
if (dashed) {
style.remove(mxConstants.STYLE_DASHED);
canvas.getGraphics().setStroke(canvas.createStroke(style));
}
translatePoint(pts, 0,
paintMarker(canvas, state, true));
translatePoint(
pts,
pts.size() - 1,
paintMarker(canvas, state, false));
if (dashed) {
// Replace the dash pattern
style.put(mxConstants.STYLE_DASHED, dashedValue);
canvas.getGraphics().setStroke(canvas.createStroke(style));
}
// Paints the shape and restores the graphics object
if (state.getAbsolutePointCount() == 4) {
double sx = state.getAbsolutePoint(0).getX();
double sy = state.getAbsolutePoint(0).getY();
double tx1 = state.getAbsolutePoint(1).getX();
double ty1 = state.getAbsolutePoint(1).getY();
double tx2 = state.getAbsolutePoint(2).getX();
double ty2 = state.getAbsolutePoint(2).getY();
double ex = state.getAbsolutePoint(3).getX();
double ey = state.getAbsolutePoint(3).getY();
Path2D.Double p = new Path2D.Double();
p.moveTo((int) sx, (int) sy);
p.quadTo((int) tx2, (int) ty2, (int) ex, (int) ey);
// p.curveTo((int) tx1, (int) ty1, (int) tx2, (int) ty2, (int) ex, (int) ey);
canvas.getGraphics().draw(p);
} else if (state.getAbsolutePointCount() == 3) {
double sx = state.getAbsolutePoint(0).getX();
double sy = state.getAbsolutePoint(0).getY();
double tx = state.getAbsolutePoint(1).getX();
double ty = state.getAbsolutePoint(1).getY();
double ex = state.getAbsolutePoint(2).getX();
double ey = state.getAbsolutePoint(2).getY();
Path2D.Double p = new Path2D.Double();
p.moveTo((int) sx, (int) sy);
p.quadTo((int) tx, (int) ty, (int) ex, (int) ey);
canvas.getGraphics().draw(p);
}
}
}
private void translatePoint(List<mxPoint> points, int index, mxPoint offset) {
if (offset != null) {
mxPoint pt = (mxPoint) points.get(index).clone();
pt.setX(pt.getX() + offset.getX());
pt.setY(pt.getY() + offset.getY());
points.set(index, pt);
}
}
}
}