Newer
Older
MagnetRON / src / org / ntlab / deltaViewer / DeltaViewer.java
Aki Hongo on 3 Mar 2020 46 KB first commit
package org.ntlab.deltaViewer;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Point2D;
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 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.deltaViewer.Edge.TypeName;
import org.ntlab.deltaExtractor.Alias.AliasType;
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.model.mxCell;
import com.mxgraph.model.mxICell;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxPoint;
import com.mxgraph.view.mxGraphView;

/**
 * Make and display JGraph of extracted delta.
 * 
 * @author Nitta Lab.
 */
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 List<Alias> aliasList;
	
	private Map<String, VertexObject> objectToVertexMap = new HashMap<>();
	private Map<MethodExecution, VertexMethodExecution> 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 curNumFrame = 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 - 50, 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);    
    	deltaAnimation = new DeltaAnimation(mxgraph, mxgraphComponent);
	}

	public DeltaViewer(ExtractedStructure extractedStructure, DeltaAliasCollector deltaAliasCollector) {
		this();
		this.eStructure = extractedStructure;
		this.deltaAliasCollector = deltaAliasCollector;
		aliasList = new ArrayList<>(deltaAliasCollector.getAliasList());
//    	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) {
			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);
    	
		while(coordinatorPoint.getX() - (150 * (eStructure.getDelta().getDstSide().size())) < 0) {
			coordinatorPoint.setX(coordinatorPoint.getX() + 150);
		}
		
    	makeVertexObject();
		makeEdgeObject();

		// Fit graph size in visiable JFrame.
		mxGraphView view = mxgraphComponent.getGraph().getView();
		int componentWidth = mxgraphComponent.getWidth();
		int viewWidth = (int) view.getGraphBounds().getWidth();
		scale = (double)componentWidth/viewWidth;
		view.setScale(scale);
		deltaAnimation.setScale(scale);
		System.out.println(componentWidth + ", " + viewWidth + ", " + scale);
	}
	
	/** Display graph on JFrame. */
	public void display() {
		setCellStyles();
    	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 cell styles. */
    private void setCellStyles() {
    	List<Object> vertexObject = new ArrayList<>();
    	List<Object> alignMiddleVertex = new ArrayList<>();
    	List<Object> alignTopVertex = new ArrayList<>();
    	List<Object> edgeObject = new ArrayList<>();
    	List<Object> edgeMethodExec = new ArrayList<>();
    	List<Object> roundEdge = new ArrayList<>();

    	for (VertexObject vertex: objectToVertexMap.values()) {
			vertexObject.add(vertex.getCell());
			if(vertex.getMethodExecutions().size() == 0) {
				alignMiddleVertex.add(vertex.getCell());
			} else {
				alignTopVertex.add(vertex.getCell());
			}
    	}
    	
    	List<VertexMethodExecution> 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 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.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());
	}
	
	private Point getAbsolutePointforCell(Object object) {
		mxICell cell = (mxICell) object;
		Point p1 = cell.getGeometry().getPoint();
		if(cell.getParent().getValue() == null) {
			return p1;
		}
		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 occurance point etc.
	 */
	public void stepToAnimation(Alias alias) {
	     try {
	 		stepToAnimation(aliasList.indexOf(alias));
	    } catch (IndexOutOfBoundsException e) {
	    	stepToAnimation(-1);	
	    }
	}

	/**
	 * Parent : Step to animation of specified numFrame.
	 * 
	 * @param numFrame Current animation frame.
	 */
	public void stepToAnimation(int numFrame) {
	     try {
	    	 Alias alias = aliasList.get(numFrame);
	 		makeAnimation(aliasList.get(curNumFrame + 1), alias);
			curNumFrame = aliasList.indexOf(alias);
	    } catch (IndexOutOfBoundsException e) {
	    	if (numFrame == - 1) {
	    		System.out.println("ERROR : Not exist alias.");
	    	} else {
				System.out.println("\r\nLast Animation.");
	    		makeLastAnimation(aliasList.get(aliasList.size() - 1));	
	    	}
	    }
	}
	
	/**
	 * Make animation from fromAlias to toAlias.
	 * 
	 * @param fromAlias 
	 * @param toAlias
	 */
	private void makeAnimation(Alias fromAlias, Alias toAlias) {
		for (int i = aliasList.indexOf(fromAlias); i <= aliasList.indexOf(toAlias); i++) {
			Alias alias = aliasList.get(i);
			System.out.println("\r\n" + alias.getObjectId() + ", " + alias.getMethodSignature() + " l." + alias.getLineNo() + " : " + alias.getAliasType().toString());
			switch(alias.getAliasType()) {
			case RETURN_VALUE:
				moveObjectVertex(alias);
				break;
			case METHOD_INVOCATION:
				removeVertexMethodExecution(alias);
				moveObjectVertex(alias);
				break;
			case FORMAL_PARAMETER:
				moveObjectVertex(alias);
				break;
			case ACTUAL_ARGUMENT:
				moveObjectVertex(alias);
				break;
			case THIS:
				if (curNumFrame == 0) {
					makeVertexMethodExecution(alias);
				}
				break;
			case RECEIVER:
				// Make VertexMethodExecution of called method execution.
				MethodExecution calledMethodExec = ((MethodInvocation) alias.getOccurrencePoint().getStatement()).getCalledMethodExecution();
				if (!methodExecToVertexMap.containsKey(calledMethodExec)) {
					makeVertexMethodExecution(alias, calledMethodExec.getSignature(), calledMethodExec);
				}
				break;
			default:
				break;
			}
		}
	}
	
	/**
	 * Make last animation of extracted delta.
	 * 
	 * @param alias Last index alias.
	 */
	private void makeLastAnimation(Alias alias) {
		// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
		mxgraph.getModel().beginUpdate();
		try {
			// Make ObjectEdge and reset position of vertexObject, remove vertexMethodExecution.
			for(Statement statement: alias.getMethodExecution().getStatements()) {
				if(statement instanceof FieldUpdate) {
					FieldUpdate fieldUpdateStatement = (FieldUpdate) statement;
					String fieldNames[] = fieldUpdateStatement.getFieldName().split("\\.");
					String fieldName = fieldNames[1];
					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);
					Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldUpdateStatement.getFieldName(), fieldName, objectToVertexMap.get(sourceObjectId).getCell(), objectToVertexMap.get(targetObjectId).getCell());

					edgeMap.put(fieldUpdateStatement.getFieldName(), new Edge(fieldName, TypeName.Reference, edge));
					System.out.println("last" + objectToVertexMap.get(targetObjectId).getInitialX() + ", " + objectToVertexMap.get(targetObjectId).getInitialY());
					System.out.println(targetCell.getParent());
					targetCell.getParent().remove(targetCell);
					targetCell.setParent(mxDefaultParent);
					targetCell.getGeometry().setX(absolutePointTargetCell.getX());
					targetCell.getGeometry().setY(absolutePointTargetCell.getY());

					deltaAnimation.setVertexAnimation(targetCell, new mxPoint(objectToVertexMap.get(targetObjectId).getInitialX(), objectToVertexMap.get(targetObjectId).getInitialY()));
					deltaAnimation.startVertexAnimation();
					System.out.println(targetCell.getParent());
					targetCell.getGeometry().setX(objectToVertexMap.get(targetObjectId).getInitialX());
					targetCell.getGeometry().setY(objectToVertexMap.get(targetObjectId).getInitialY());
		    		removeCalledVertexMethodExecution(objectToVertexMap.get(sourceObjectId), alias.getMethodExecution().getCallerMethodExecution(), alias.getMethodExecution());
		    		updateVertexObjectSize();
		    		display();
				}
			}
		} finally {
			  mxgraph.getModel().endUpdate();
		}

		// 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);
	    	for(int i = 0; i < methodExecList.size() - 1; i++) {
	    		String objectId = methodExecList.get(i).getThisObjId();
	    		VertexObject sourceVertexObject = objectToVertexMap.get(objectId); // sourceVertex
	    		MethodExecution methodExec = methodExecList.get(i);
	    		for(Statement statement: methodExec.getStatements()) {
	    			if(statement instanceof MethodInvocation) {
	    	    		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(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();
						}
			    		removeCalledVertexMethodExecution(sourceVertexObject, methodExec.getCallerMethodExecution(), methodExec);
			    		updateVertexObjectSize();
//			    		removeVertexMethodExecution(sourceVertexObject, methodExec);
	    				display();
	    				break;
	    			}
	    		}
	    	}
		} finally {
			  mxgraph.getModel().endUpdate();
		}

	}

	/** Make VertexObject. */
	private void makeVertexObject() {    	
    	//Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
		// �¶�ã(0, 0)
    	double xCor = coordinatorPoint.getX();
		double yCor = coordinatorPoint.getY();
		double time = 150;

		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);
				if (!ref.isCreation() || !ref.getSrcObjectId().equals(ref.getDstObjectId())) {
					if(!objectToVertexMap.containsKey(ref.getSrcObjectId())) {
						Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcClassName(), ref.getSrcClassName(), xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. 
//				    	mxgraph.updateCellSize(vertex, true);
				    	objectToVertexMap.put(ref.getSrcObjectId(), new VertexObject(ref.getSrcClassName(), vertex, xCor + (time * ((srcSideSize - 1) - i)), yCor + (time * ((srcSideSize - 1) - i))));
					}
					if(!objectToVertexMap.containsKey(ref.getDstObjectId())) {
						Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getDstClassName(), ref.getDstClassName(), 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 VertexObject(ref.getDstClassName(), vertex, xCor + (time * (srcSideSize - i)), yCor + (time * (srcSideSize - i))));
					}
				}
			}

			// dstSide
			int dstSideSize = delta.getDstSide().size();
			for (int i = dstSideSize - 1; i >= 0; i--) {
				Reference ref = delta.getDstSide().get(i);
				if (!ref.isCreation() || !ref.getSrcObjectId().equals(ref.getDstObjectId())) {
					Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getDstClassName(), ref.getDstClassName(), xCor - (time * (dstSideSize - i)), yCor + (time * (dstSideSize - i)), VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. 
					objectToVertexMap.put(ref.getDstObjectId(), new VertexObject(ref.getDstClassName(), vertex, xCor - (time * (dstSideSize - i)), yCor + (time * (dstSideSize - i))));
				}
			}
    	} finally {
    		  mxgraph.getModel().endUpdate();
      	}
    }
		
	/**
	 * SourceVertex move targetVertex.
	 * 
	 * @param alias
	 */
	private void moveObjectVertex(Alias alias) {
		// sourceVertex
		VertexObject sourceVertexObject = objectToVertexMap.get(alias.getObjectId());
		// targetVertex
		VertexMethodExecution targetVertexMethodExec = methodExecToVertexMap.get(alias.getMethodExecution());
		
		moveObjectVertex(alias, sourceVertexObject, targetVertexMethodExec);
		updateVertexObjectSize();
	}

	/**
	 * Parent : Source VertexObject move target VertexMethodExecution.
	 * 
	 * @param alias
	 * @param sourceVertexObject Source VertexObject.
	 * @param targetVertexMethodExec Target VertexMethodExecution.
	 */
	private void moveObjectVertex(Alias alias, VertexObject sourceVertexObject, VertexMethodExecution 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, VertexObject sourceVertexObject, VertexMethodExecution 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 callercallerMethodExec = callerMethodExec.getCallerMethodExecution();		
		if (methodExecToVertexMap.containsKey(callercallerMethodExec) && methodExecToVertexMap.get(callercallerMethodExec).getLocals().contains(sourceVertexObject)) {
			methodExecToVertexMap.get(callercallerMethodExec).getLocals().remove(sourceVertexObject);
			System.out.println(methodExecToVertexMap.get(callercallerMethodExec).getLabel() + " :removeLocal: " + sourceVertexObject.getLabel());
		}

		if (methodExecToVertexMap.containsKey(callercallerMethodExec) && methodExecToVertexMap.get(callercallerMethodExec).getArguments().contains(sourceVertexObject)) {
			methodExecToVertexMap.get(callercallerMethodExec).getArguments().remove(sourceVertexObject);
			System.out.println(methodExecToVertexMap.get(callercallerMethodExec).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() + 1;
			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);
			
			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 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.getLocals().add(sourceVertexObject);
			System.out.println(targetVertexMethodExec.getLabel() + " :Local: " + sourceVertexObject.getLabel());
		} finally {
			  mxgraph.getModel().endUpdate();
		}
	}
	
	/**
	 * Source VertexObject move target VertexMethodExecution to Argument position from MethodExecution.
	 * 
	 * @param methodExec MethodExecution.
	 * @param sourceVertexObject
	 * @param targetVertexMethodExec
	 */
	private void moveArgumentObjectVertex(MethodExecution methodExec, VertexObject sourceVertexObject, VertexMethodExecution 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);
			}
			
			sourceCell.setParent(targetCell.getParent());
			targetCell.getParent().insert(sourceCell);
			sourceCell.getGeometry().setX(sourceX - sourceCell.getParent().getGeometry().getX());
			sourceCell.getGeometry().setY(sourceY - sourceCell.getParent().getGeometry().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(targetVertexMethodExec.getLabel() + " :Argument: " + sourceVertexObject.getLabel());
		} 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, VertexObject sourceVertexObject, VertexMethodExecution 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 (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);
			sourceCell.getGeometry().setX(sourceX - sourceCell.getParent().getGeometry().getX());
			sourceCell.getGeometry().setY(sourceY - sourceCell.getParent().getGeometry().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.getGeometry().setX(targetCell.getGeometry().getX() - overlapWidth);
			sourceCell.getGeometry().setY(targetCell.getGeometry().getY() - overlapHeight + (sourceHeight * time));
			targetVertexMethodExec.getArguments().add(sourceVertexObject);			
			System.out.println(targetVertexMethodExec.getLabel() + " :Argument: " + sourceVertexObject.getLabel());
		} finally {
			  mxgraph.getModel().endUpdate();
		}
	}
	
	/** Update VertexObject size. */
		private void updateVertexObjectSize() {
			// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology    	
			mxgraph.getModel().beginUpdate();
			try {
				for (VertexObject vertexObject: objectToVertexMap.values()) {
					mxCell vertexObjectCell = ((mxCell) vertexObject.getCell());
			    	int time = vertexObjectCell.getChildCount();
			    	if (time == 0) {
			    		time = 1;
			    	}

			    	if(vertexObjectCell.getGeometry().getWidth() != VERTEX_OBJECT_SIZE.getWidth() * time) {
			    		Dimension targetDimension = new Dimension();
			    		targetDimension.setSize(VERTEX_OBJECT_SIZE.getWidth() * time, VERTEX_OBJECT_SIZE.getHeight() * time);
			    		deltaAnimation.setResizeVertexAnimation(vertexObjectCell, targetDimension);
			    		deltaAnimation.startResizeVertexAnimation();
			    	}	
				}
			}finally {
				  mxgraph.getModel().endUpdate();
			}

			show(mxDefaultParent);
		}

		private void show(mxICell cell) {
			for(Object object: mxgraph.getChildCells(cell)) {
				System.out.println(object);
			}

		}
	/**
	 * 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. */
    private void makeEdgeObject() {
    	Map<String, Collection<String>> fieldNameMap = new HashMap<>();

    	// Format field name. 
		for(Alias alias: aliasList) {	
			if(alias.getAliasType().equals(AliasType.THIS)) {
				for(Statement statement: alias.getMethodExecution().getStatements()) {
					if(statement instanceof FieldAccess) {
						String fieldNames[] = formatFieldName(((FieldAccess)statement).getFieldName());
						if(fieldNameMap.get(fieldNames[0]) == null) {
							fieldNameMap.put(fieldNames[0], new HashSet<String>());
						}
						fieldNameMap.get(fieldNames[0]).add(fieldNames[1]);
					}
				}
			}
		}
		
		mxgraph.getModel().beginUpdate();
		try {
			// Make object edge in JGraphT and draw this in JGraphX.
			Delta delta = eStructure.getDelta();
			int srcSideSize = delta.getSrcSide().size();
			int dstSideSize = delta.getDstSide().size();
			for (int i = srcSideSize - 1; i >= 0; i--) {
				Reference ref = delta.getSrcSide().get(i);
				if (!ref.isCreation() || !ref.getSrcObjectId().equals(ref.getDstObjectId())) {
					for(String fieldName: fieldNameMap.get(ref.getSrcClassName())) {
						// BUG : contains -> equals
						if(ref.getDstClassName().contains(fieldName.toUpperCase())) {
							Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldName, fieldName, objectToVertexMap.get(ref.getSrcObjectId()).getCell(), objectToVertexMap.get(ref.getDstObjectId()).getCell());
			    			((mxCell)edge).setStyle("exitX=1;exitY=1;exitPerimeter=1;entryX=0;entryY=0;entryPerimeter=1;");
							edgeMap.put(ref.getSrcClassName() + "." + fieldName, new Edge(fieldName, TypeName.Reference, edge));
							break;
						}
					}
				}
			}

			for (int i = dstSideSize - 1; i >= 0; i--) {
				Reference ref = delta.getDstSide().get(i);
				if (!ref.isCreation() || !ref.getSrcObjectId().equals(ref.getDstObjectId())) {
					for (String fieldName: fieldNameMap.get(ref.getSrcClassName())) {
						// BUG : contains -> equals
						if (ref.getDstClassName().contains(fieldName.toUpperCase())) {
							Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldName, fieldName, objectToVertexMap.get(ref.getSrcObjectId()).getCell(), objectToVertexMap.get(ref.getDstObjectId()).getCell());
			    			((mxCell)edge).setStyle("exitX=0;exitY=1;exitPerimeter=1;entryX=1;entryY=0;entryPerimeter=1;");
			    			edgeMap.put(ref.getSrcClassName() + "." + fieldName, new Edge(fieldName, TypeName.Reference, edge));
							break;
						}
					}
				}
			}
    	} finally {
  		  mxgraph.getModel().endUpdate();
    	}
	}
	
    /**
     * Make VertexMethodExecution.
     * 
     * @param alias
     */
	private void makeVertexMethodExecution(Alias alias) {
		makeVertexMethodExecution(alias, alias.getMethodSignature(), alias.getMethodExecution());
	}
	
	/**
	 * Parent : Make VertexMethodExecution.
	 * 
	 * @param alias
	 * @param methodSignature Called or this MethodSignature.
	 * @param methodExec Called or this MethodExecution.
	 */
	private void makeVertexMethodExecution(Alias alias, String methodSignature, MethodExecution methodExec) {
    	
    	if (methodSignature.contains(" ")) {
    		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();
    		Object object = objectToVertexMap.get(objectId).getCell();
    		double xCor = VERTEX_OBJECT_SIZE.getWidth() * 0.1;
    		double yCor =  VERTEX_OBJECT_SIZE.getHeight() * 0.5;
    		int time = objectToVertexMap.get(objectId).getMethodExecutions().size();
    		
			Object vertex = mxgraph.insertDeltaVertex(object, methodSignature, methodSignature, "fillColor=white"); //creates a white vertex. 
			System.out.println((mxICell)vertex);

			VertexMethodExecution vertexMethodExecution =  new VertexMethodExecution(methodSignature, vertex, xCor * (time + 1), yCor * (time + 1), 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);
			}
			objectToVertexMap.get(objectId).addMethodExecution(vertexMethodExecution);
    	} finally {
    		  mxgraph.getModel().endUpdate();
      	}
    	makeEdgeMethodExecution();
	}
	
	/**
	 * Remove VertexMethodExecution on AliasType is MethodInvocation of alias.
	 * 
	 * @param alias
	 */
	private void removeVertexMethodExecution(Alias alias) {
		// sourceVertex
		VertexObject sourceVertexObject = objectToVertexMap.get(alias.getObjectId());
		MethodExecution methodExec = alias.getMethodExecution();
		
		if(alias.getAliasType().equals(AliasType.METHOD_INVOCATION)) {
			MethodExecution calledMethodExec = ((MethodInvocation) alias.getOccurrencePoint().getStatement()).getCalledMethodExecution();
			removeCalledVertexMethodExecution(sourceVertexObject, methodExec, calledMethodExec);
		} else {
			removeVertexMethodExecution(sourceVertexObject, methodExec);
		}
	}

	/**
	 * Remove VertexMethodExecution on AliasType is MethodInvocation of alias.
	 * 
	 * @param sourceVertexObject
	 * @param methodExec
	 */
	private void removeVertexMethodExecution(VertexObject 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()).getMethodExecutions().remove(methodExecToVertexMap.get(methodExec));
			methodExecToVertexMap.remove(methodExec);
			edgeMap.remove(methodExec.getSignature());
			updateVertexObjectSize();
		}
	}

	/**
	 * Remove CalledVertexMethodExecution on AliasType is MethodInvocation of alias.
	 * 
	 * @param sourceVertexObject
	 * @param methodExec
	 * @param calledMethodExec
	 */
	private void removeCalledVertexMethodExecution(VertexObject sourceVertexObject, MethodExecution methodExec, MethodExecution calledMethodExec) {	

		//  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();
			Point absolutPointSourceVertexCell = getAbsolutePointforCell(sourceVertexCell);

			// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
			mxgraph.getModel().beginUpdate();
			try {
				mxgraph.removeCells(mxgraph.getEdgesBetween(sourceVertexCell, targetVertexCell));
					try {
						mxICell cloneTargetVertexCell = (mxICell) mxgraph.addCell(targetVertexCell.clone());
						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();
			}

			targetVertexCell.getParent().remove(targetVertexCell);
			targetVertexCell.setParent(mxDefaultParent); 
			mxgraph.removeCells(new Object[] {targetVertexCell});
			objectToVertexMap.get(calledMethodExec.getThisObjId()).getMethodExecutions().remove(methodExecToVertexMap.get(calledMethodExec));
			methodExecToVertexMap.get(calledMethodExec).getLocals().remove(sourceVertexObject);
			methodExecToVertexMap.remove(calledMethodExec);
			edgeMap.remove(methodExec.getSignature());
//			updateVertexObjectSize();
		}
	}


	/** Make EdgeMethodExecution. */
	private void makeEdgeMethodExecution() {
		List<MethodExecution> methodExecList = new ArrayList<>(methodExecToVertexMap.keySet());
	
		// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology    	
		mxgraph.getModel().beginUpdate();
		try {
			// 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();
	    			Point absolutPointSourceVertexCell = getAbsolutePointforCell(sourceVertexCell);
	    			Point absolutPointTargetVertexCell = getAbsolutePointforCell(targetVertexCell);

//	    			System.out.println("start : " + sourceVertexCell.getGeometry().getCenterX() + ", " + (sourceVertexCell.getGeometry().getY() + sourceVertexCell.getGeometry().getHeight()) +  ", " + targetVertexCell.getGeometry().getCenterX() + ", " + targetVertexCell.getGeometry().getY());
//	    			deltaAnimation.setEdgeAnimation(new mxPoint(sourceVertexCell.getGeometry().getCenterX(), sourceVertexCell.getGeometry().getY() + sourceVertexCell.getGeometry().getHeight()), new mxPoint(targetVertexCell.getGeometry().getCenterX(), targetVertexCell.getGeometry().getY()));
	    			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();
	    			targetVertexCell.setVisible(true);
	    			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;");
	    			edgeMap.put(methodSignature, new Edge(methodSignature, TypeName.Call, edge));
					}
				}
		} finally {
			  mxgraph.getModel().endUpdate();
		}
	}
	
	private int countChildVertex(VertexObject vertexObject) {
    	int time = vertexObject.getMethodExecutions().size();
    	if(time == 0) {
    		return 1;
    	}
    	for(VertexMethodExecution vertexMethodExecution: vertexObject.getMethodExecutions()) {
    		for(VertexObject vo: vertexMethodExecution.getLocals()) {
    			time += countChildVertex(vo);
    		}
    		for(VertexObject 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(" ");
		methodSignature = methodSignatures[1];
		methodSignature += "()";
		return methodSignature;
	}
}