Newer
Older
MagnetRON / src / org / ntlab / deltaViewer / CollaborationViewer.java
Aki Hongo on 30 Dec 2020 24 KB #22 Change to call method execution such as addElement(), add() in
package org.ntlab.deltaViewer;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.ntlab.deltaExtractor.Alias;
import org.ntlab.deltaExtractor.IAliasCollector;
import org.ntlab.deltaExtractor.Alias.AliasType;
import org.ntlab.deltaViewer.Edge.TypeName;
import org.ntlab.trace.ArrayAccess;
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 org.ntlab.trace.TracePoint;

import com.mxgraph.model.mxICell;
import com.mxgraph.util.mxPoint;
import com.mxgraph.view.mxGraphView;

public class CollaborationViewer extends MagnetRONViewer {
	private IObjectCallGraph objectCallGraph;

	private double scale = 1;
	
	public CollaborationViewer() {
		super();
	}
	
	/**
	 * Set objectCallGraph and aliasCollector, create vertex object and edge object.
	 * @param objectCallGraph
	 * @param aliasCollector
	 */
	public void init(IObjectCallGraph objectCallGraph, IAliasCollector aliasCollector, IObjectLayout layout) {
		this.objectCallGraph = objectCallGraph;
		this.aliasCollector = aliasCollector;
		createObjectVertices(this.objectCallGraph);
		layout.execute(objectCallGraph, aliasCollector, objectToVertexMap);
		createEdgeToObject(this.objectCallGraph, this.aliasCollector);
	}
		
	/**
	 * Initialize animation. (再生ボタンを押すとき)
	 */
	public void initAnimation() {
//		reflectCoordinates(mxgraph); // objectVertexにmxGraphの座標を反映させる(ユーザが指定した座標位置を反映)

		// 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);

//		scale = (double)componentWidth/viewWidth;
		System.out.println(", " + scale);
//		scale = 1.5;
		view.setScale(scale);
		deltaAnimation.setScale(scale);
		update();
	}
	
	/**
	 * Step to animation of specified alias. 
	 * 
	 * @param alias Alias type and occurrence point etc.
	 */
	public void stepToAnimation(Alias alias) {
		try {
			stepToAnimation(aliasCollector.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) {
		// TODO Implement doLastAnimation to support plural Delta.
		// TOD curFrame debug.
		System.out.println("Frame: " + curFrame + "->" + numFrame);
//		if (numFrame - curFrame == 1) {
			List<TracePoint> relatedPoints = objectCallGraph.getRelatedPoints();
			List<Alias> aliasList = aliasCollector.getAliasList();
			Alias curFrameAlias = (0 < numFrame && numFrame <= aliasList.size()) ? aliasList.get(numFrame- 1) : null;
			Alias numFrameAlias = (0 <= numFrame && numFrame < aliasList.size()) ? aliasList.get(numFrame) : null;

			if (numFrameAlias != null) {
				if (curFrameAlias != null) {
					for (TracePoint rp: relatedPoints) {
						if (curFrameAlias.getTimeStamp() < rp.getStatement().getTimeStamp() && rp.getStatement().getTimeStamp() < numFrameAlias.getTimeStamp()) {
							System.out.println("\r\nLast Animation.");
							doLastAnimation(numFrame, rp);	
							return;
						}
					}
				}
				doAnimation(curFrame, numFrame);
			} else if (curFrameAlias != null && numFrameAlias == null) {
				System.out.println("\r\nLast Animation.");
				doLastAnimation(numFrame, relatedPoints.get(relatedPoints.size() - 1));	
			} else {
				System.out.println("ERROR : Not exist alias.");
			}
//		} else {
			// TODO Considering fast-forwarding animations. 			
//		}
	}

	private void doLastAnimation(int numFrame, TracePoint relatedPoint) {
		// TODO Implement doLastAnimation to support plural Delta.
		outputLog();
		curFrame = numFrame;
		List<Alias> aliasList = aliasCollector.getAliasList();
		Alias prevAlias = aliasList.get(numFrame - 1);
		Alias nextAlias = (numFrame < aliasList.size()) ? aliasList.get(numFrame) : null;

		// Make ObjectEdge and reset position of vertexObject, remove vertexMethodExecution.
		Statement statement = relatedPoint.getStatement();
		MethodExecution prevMethodExec = prevAlias.getMethodExecution();
		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);

			if (methodExecToVertexMap.containsKey(prevMethodExec)) {
				if (methodExecToVertexMap.get(prevMethodExec).getLocals().contains(targetObjectVertex)) {
					methodExecToVertexMap.get(prevMethodExec).getLocals().remove(targetObjectVertex);
					System.out.println(methodExecToVertexMap.get(prevMethodExec).getLabel() + " :removeLocal: " + targetObjectVertex.getLabel());
				} else if (methodExecToVertexMap.get(prevMethodExec).getArguments().contains(targetObjectVertex)) {
					methodExecToVertexMap.get(prevMethodExec).getArguments().remove(targetObjectVertex);
					System.out.println(methodExecToVertexMap.get(prevMethodExec).getLabel() + " :removeArgument: " + targetObjectVertex.getLabel());
				}
			}
			if (nextAlias == null || (nextAlias != null && !prevMethodExec.getSignature().equals(nextAlias.getMethodSignature()))) {
				removeCalledMethodExecutionVertex(objectToVertexMap.get(sourceObjectId), prevMethodExec.getCallerMethodExecution(), prevMethodExec);
				updateObjectVertices();
			}
		}

		if(statement instanceof MethodInvocation) {
			MethodInvocation methodInvStatement = (MethodInvocation) statement;
			MethodExecution calledMethodExec = methodInvStatement.getCalledMethodExecution();
			String methodSignature = calledMethodExec.getSignature();
			String srcClassName = null;
			String srcObjId = null;
			String tgtObjId = null;

			//ArrayやListのときだけラベルを付ける(確実に分かっているものとき)getSignature->contains("List.get(") || "Map.get(") <ホワイトリスト>
//				if (methodExec.getSignature().contains("List.add(") ||
//						methodExec.getSignature().contains("Map.put(")) {
			if (calledMethodExec.isCollectionType()
					&& (methodSignature.contains("add(") 
							|| methodSignature.contains("set(") 
							|| methodSignature.contains("put(") 
							|| methodSignature.contains("push(") 
							|| methodSignature.contains("addElement("))) {

				srcClassName = calledMethodExec.getThisClassName();
				srcObjId = calledMethodExec.getThisObjId();
				tgtObjId = calledMethodExec.getArguments().get(0).getId();
				ObjectVertex tgtObjectVertex = objectToVertexMap.get(tgtObjId);

				if (!methodExecToVertexMap.containsKey(calledMethodExec)) {
					createMethodExecutionVertex(calledMethodExec.getThisObjId(), methodInvStatement.getCallerSideMethodName(), calledMethodExec);
					update();
					moveArgumentObjectVertex(calledMethodExec, tgtObjectVertex, methodExecToVertexMap.get(calledMethodExec));
					update();
					createObjectRefrence(srcClassName, srcObjId, tgtObjId);
					removeCalledMethodExecutionVertex(null, prevMethodExec, calledMethodExec);
				} else {
					createObjectRefrence(srcClassName, srcObjId, tgtObjId);
				}
				if (methodExecToVertexMap.containsKey(prevMethodExec)) {
					if (methodExecToVertexMap.get(prevMethodExec).getLocals().contains(tgtObjectVertex)) {
						methodExecToVertexMap.get(prevMethodExec).getLocals().remove(tgtObjectVertex);
						System.out.println(methodExecToVertexMap.get(prevMethodExec).getLabel() + " :removeLocal: " + tgtObjectVertex.getLabel());
					} else if (methodExecToVertexMap.get(prevMethodExec).getArguments().contains(tgtObjectVertex)) {
						methodExecToVertexMap.get(prevMethodExec).getArguments().remove(tgtObjectVertex);
						System.out.println(methodExecToVertexMap.get(prevMethodExec).getLabel() + " :removeArgument: " + tgtObjectVertex.getLabel());
					}
				}
				List<MethodExecution> methodExecList = new ArrayList<>(methodExecToVertexMap.keySet());
				System.out.println(methodExecList.size());
				if (nextAlias == null || (nextAlias != null && !prevMethodExec.getSignature().equals(nextAlias.getMethodSignature()))) {
					if (methodExecList.size() > 1) {
						removeCalledMethodExecutionVertex(null, prevMethodExec.getCallerMethodExecution(), prevMethodExec);
					} else {
						removeCalledMethodExecutionVertex(null, null, prevMethodExec);						
					}
				}
				updateObjectVertices();
			} else {
				// this to another
				srcClassName = methodInvStatement.getThisClassName();
				srcObjId = methodInvStatement.getThisObjId();
				tgtObjId = calledMethodExec.getReturnValue().getId();
				ObjectVertex tgtObjectVertex = objectToVertexMap.get(tgtObjId);

				createObjectRefrence(srcClassName, srcObjId, tgtObjId);
				if (methodExecToVertexMap.containsKey(prevMethodExec)) {
					if (methodExecToVertexMap.get(prevMethodExec).getLocals().contains(tgtObjectVertex)) {
						methodExecToVertexMap.get(prevMethodExec).getLocals().remove(tgtObjectVertex);
						System.out.println(methodExecToVertexMap.get(prevMethodExec).getLabel() + " :removeLocal: " + tgtObjectVertex.getLabel());
					} else if (methodExecToVertexMap.get(prevMethodExec).getArguments().contains(tgtObjectVertex)) {
						methodExecToVertexMap.get(prevMethodExec).getArguments().remove(tgtObjectVertex);
						System.out.println(methodExecToVertexMap.get(prevMethodExec).getLabel() + " :removeArgument: " + tgtObjectVertex.getLabel());
					}
				}
				if (nextAlias == null || (nextAlias != null && !calledMethodExec.getSignature().equals(nextAlias.getMethodSignature()))) {
					removeCalledMethodExecutionVertex(objectToVertexMap.get(srcObjId), prevMethodExec, calledMethodExec);
					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> meList = new ArrayList<>(methodExecToVertexMap.keySet());
			Collections.reverse(meList);
			System.out.println(meList.size());
			for(int i = 0; i < meList.size(); i++) {
				String objectId = meList.get(i).getThisObjId();
				ObjectVertex sourceVertexObject = objectToVertexMap.get(objectId); // sourceVertex
				MethodExecution me = meList.get(i);
				if (nextAlias != null && me.getSignature().equals(nextAlias.getMethodSignature())) break;
				if (i != meList.size()-1) {
					for(Statement st: me.getStatements()) {
						if(st instanceof MethodInvocation) {
							MethodExecution calledMethodExec = ((MethodInvocation) st).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 + ", " + me.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, me.getCallerMethodExecution(), me);
								updateObjectVertices();
//					    		removeVertexMethodExecution(sourceVertexObject, methodExec);
//			    				update();
								break;
							}
						}
					}
				}  else {
					outputLog();

					// Change!
					List<ObjectVertex> arguments = new ArrayList<>(methodExecToVertexMap.get(me).getArguments());
					List<ObjectVertex> locals = new ArrayList<>(methodExecToVertexMap.get(me).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(me).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(me).getLocals().remove(vo);
						}
					}
					updateObjectVertices();	    			
				}
			}
		} finally {
			mxgraph.getModel().endUpdate();
		}
		update();		
	}

	/**
	 * Create vertices(mxGraph) and objectVertices in objectToVertexMap. Vertices(mxGraph) coordinate are appropriate. 
	 * @param objectCallGraph
	 */
	private void createObjectVertices(IObjectCallGraph objectCallGraph) {
		//Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
		mxgraph.getModel().beginUpdate();
		try {
			// Create vertices(mxGraph) and objectVertices.
			List<Reference> refList = objectCallGraph.getReferences();
			int ocgSize = refList.size();
			double vertexObjWidth = VERTEX_OBJECT_SIZE.getWidth();
			double vertexObjHeight = VERTEX_OBJECT_SIZE.getHeight();
			
			{
				MethodExecution coordinator = objectCallGraph.getStartPoints().get(0);
				String coordinatorObjId = coordinator.getThisObjId();
				String coordinatorClassName = coordinator.getThisClassName();
				Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, coordinatorObjId, coordinatorClassName, 0, 0, VERTEX_OBJECT_SIZE.getWidth(), VERTEX_OBJECT_SIZE.getHeight(), "fillColor=white"); //creates a white vertex. 
				objectToVertexMap.put(coordinatorObjId, new ObjectVertex(coordinatorClassName, vertex, 0, 0));
			}
			
			for (int i = 0; i < ocgSize; i++) {
				Reference ref = refList.get(i);
				if (!ref.isCreation() && !ref.getSrcObjectId().equals(ref.getDstObjectId())) {
					// srcSide
					if (!objectToVertexMap.containsKey(ref.getSrcObjectId())) {
						System.out.println("srcSide: " + ref.getSrcClassName() + ", " + ref.getSrcObjectId() + ": " + ref.isCreation());
						String srcClassName = ref.getSrcClassName();
						if (srcClassName.contains("[L")) {
							srcClassName = formatArrayName(srcClassName);
						}
						Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. 
						objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, 0, 0));
					}
					// dstSide
					if (!objectToVertexMap.containsKey(ref.getDstObjectId())) {
						System.out.println("dstSide: " + ref.getDstClassName() + ", " + ref.getDstObjectId());
						String dstClassName = ref.getDstClassName();
						if (dstClassName.contains("[L")) {
							dstClassName = formatArrayName(dstClassName);
						}
						Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getDstObjectId(), dstClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. 		
						objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), vertex, 0, 0));
					}
				} else {
					if (!objectToVertexMap.containsKey(ref.getSrcObjectId())) {
						String srcClassName = ref.getSrcClassName();
						if (srcClassName.contains("[L")) {
							srcClassName = formatArrayName(srcClassName);
						}
						Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. 
						objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, 0, 0));
					}
					if (!objectToVertexMap.containsKey(ref.getDstObjectId())) {
						objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), null, 0, 0));
					} else {
						mxgraph.removeCells(new Object[] {objectToVertexMap.get(ref.getDstObjectId()).getCell()});
						objectToVertexMap.get(ref.getDstObjectId()).setCell(null);
					}
				}
			}
		} finally {
			mxgraph.getModel().endUpdate();
		}	
	}

	/**
	 * Create MethodExecutionVertex. Be careful to refer objectCallGraph.getStartPoints() when curFrame is 0.
	 * 
	 * @param alias
	 */
	@Override
	public void createMethodExecutionVertex(Alias alias) {
		String objId = alias.getObjectId();
		MethodExecution methodExec = alias.getMethodExecution();
		String methodExecSignature = methodExec.getSignature();

		if (curFrame == 0) {
			MethodExecution callerMethodExec = methodExec.getCallerMethodExecution();
			if (callerMethodExec != null && methodExecSignature != callerMethodExec.getSignature() && objectToVertexMap.containsKey(callerMethodExec.getThisObjId()) && objectCallGraph.getStartPoints().get(0) == callerMethodExec) {
				createMethodExecutionVertex(callerMethodExec.getThisObjId(), callerMethodExec.getSignature(), callerMethodExec);
			}
			createMethodExecutionVertex(objId, methodExecSignature, methodExec);
		} else if (alias.getObjectId().matches("0") && !methodExecToVertexMap.containsKey(methodExec)) {
			createMethodExecutionVertex(objId, methodExecSignature, methodExec);
		}		
	}

	/**
	 * 
	 * @param ocg
	 * @param ac
	 */
	private void createEdgeToObject(IObjectCallGraph ocg, IAliasCollector ac) {
		List<TracePoint> relatedPoints = ocg.getRelatedPoints();
		int rpIndex = 0; // relatedPoints index
		List<Alias> aliasList = ac.getAliasList();

		for (int i = 0; i < aliasList.size()-1; i++) {
			Alias curAlias = aliasList.get(i);
			Alias nextAlias = aliasList.get(i+1);
			String curAliasObjId = curAlias.getObjectId(); // srcObjId
			String nextAliasObjId = nextAlias.getObjectId(); // dstObjId
			String srcClassName = null;
			String fieldName = null;
			
			// Search for objectReference srcClassName, fieldName between curAlias and nexAlias.
			if (curAlias.getAliasType() == AliasType.THIS) {
				if (nextAlias.getAliasType() == 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 && curAliasObjId.equals(((FieldAccess)statement).getContainerObjId())) {
						String fieldNames[] = formatFieldName(((FieldAccess)statement).getFieldName());
						srcClassName = fieldNames[0];
						fieldName = fieldNames[1];
					}
				}
				System.out.println("THIS " + srcClassName + "(" + curAliasObjId + ") -> " + "(" + nextAliasObjId + "), "+ fieldName);
			}
			
			if(curAlias.getAliasType() == 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 + "(" + curAliasObjId + ") -> " + "(" +  nextAliasObjId + "),  " + fieldName);
				}
			}
			
			
			if (srcClassName != null && fieldName != null && !edgeMap.containsKey(srcClassName + "." + fieldName)) {
				// Judge AliasList contains relatedPoint. (If contains not to create edge.)
				if (rpIndex < relatedPoints.size() - 1) {
					TracePoint rp = relatedPoints.get(rpIndex);
					Map.Entry<Reference, String> rpInf = getRelatedInformation(rp);
					if (srcClassName.equals(rpInf.getKey().getSrcClassName()) && fieldName.equals(rpInf.getValue()) && curAliasObjId.equals(rpInf.getKey().getSrcObjectId()) && nextAliasObjId.equals(rpInf.getKey().getDstObjectId())) {
						rpIndex++;
						continue;
					}
				}

				// Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology.
				mxgraph.getModel().beginUpdate();
				try {
					Object srcCell = objectToVertexMap.get(curAliasObjId).getCell();
					Object dstCell = objectToVertexMap.get(nextAliasObjId).getCell();
					if (srcCell != null && dstCell != null) { // isCreation()
						System.out.println("makeEdgeObject: " + fieldName + ", " + srcClassName + " (" + srcCell.hashCode() + "), " + " (" + dstCell.hashCode() + ")"/* + ", " + dstClassName*/);
						// BUG:NullPointerException
						Object edge = mxgraph.insertDeltaEdge(mxDefaultParent, fieldName, fieldName, srcCell, dstCell);
						Point absPtSrcCell = getAbsolutePointforCell((mxICell)srcCell);
						Point absPtDstCell = getAbsolutePointforCell((mxICell)dstCell);
						setEdgePoint((mxICell)edge, absPtSrcCell, absPtDstCell);
						edgeMap.put(srcClassName + "." + fieldName, new Edge(fieldName, TypeName.Reference, edge));
					}
				} finally {
					mxgraph.getModel().endUpdate();
				}
			}
		}		
	}

}