diff --git a/src/org/ntlab/deltaExtractor/DeltaExtractor.java b/src/org/ntlab/deltaExtractor/DeltaExtractor.java index 794b9a4..f8d6644 100644 --- a/src/org/ntlab/deltaExtractor/DeltaExtractor.java +++ b/src/org/ntlab/deltaExtractor/DeltaExtractor.java @@ -844,6 +844,11 @@ if (objectId.equals(srcObject.getId())) { r = new Reference(thisObj, srcObject); r.setCollection(true); + if (methodExecution.getSignature().contains(".iterator()") + || methodExecution.getSignature().contains(".listIterator()") + || methodExecution.getSignature().contains(".entrySet()") + || methodExecution.getSignature().contains(".keySet()") + || methodExecution.getSignature().contains(".values()")) r.setCreation(true); // �C�e���[�^�I�u�W�F�N�g���𐶐������Ƃ݂Ȃ� eStructure.addSrcSide(r); srcObject = thisObj; aliasCollector.changeTrackingObject(objectId, thisObjectId, true); @@ -851,6 +856,11 @@ } else if(objectId.equals(dstObject.getId())) { r = new Reference(thisObj, dstObject); r.setCollection(true); + if (methodExecution.getSignature().contains(".iterator()") + || methodExecution.getSignature().contains(".listIterator()") + || methodExecution.getSignature().contains(".entrySet()") + || methodExecution.getSignature().contains(".keySet()") + || methodExecution.getSignature().contains(".values()")) r.setCreation(true); // �C�e���[�^�I�u�W�F�N�g���𐶐������Ƃ݂Ȃ� eStructure.addDstSide(r); dstObject =thisObj; aliasCollector.changeTrackingObject(objectId, thisObjectId, false); diff --git a/src/org/ntlab/deltaViewer/CollaborationLayout.java b/src/org/ntlab/deltaViewer/CollaborationLayout.java index edadf05..0f5ce73 100644 --- a/src/org/ntlab/deltaViewer/CollaborationLayout.java +++ b/src/org/ntlab/deltaViewer/CollaborationLayout.java @@ -27,7 +27,7 @@ import com.mxgraph.util.mxPoint; public class CollaborationLayout implements IObjectLayout { - private static final int angleStep = 15; + private static final int angleStep = 30; private mxPoint coordinatorPoint = new mxPoint(0, 100); private double step; private double padding; @@ -119,7 +119,7 @@ if (idx < 0) { references.add(r); idx = references.indexOf(r); - } + } } } else if (a.getAliasType() == AliasType.CONSTRACTOR_INVOCATION) { MethodInvocation c = (MethodInvocation) a.getOccurrencePoint().getStatement(); @@ -156,6 +156,26 @@ } } } + } else if (a.getAliasType() == AliasType.FORMAL_PARAMETER) { + MethodExecution methodExec = a.getOccurrencePoint().getMethodExecution(); + if (methodExec.isStatic()) { + // For calls to a static method. + String dstClassName = methodExec.getThisClassName(); + String srcClassName = methodExec.getCallerMethodExecution().getThisClassName(); + String dstObjId = methodExec.getThisObjId() + ":" + dstClassName; + String srcObjId = null; + if (!methodExec.getCallerMethodExecution().isStatic()) { + srcObjId = methodExec.getCallerMethodExecution().getThisObjId(); + } else { + srcObjId = methodExec.getCallerMethodExecution().getThisObjId() + ":" + srcClassName; + } + Reference r = new Reference(srcObjId, dstObjId, srcClassName, dstClassName); + idx = references.indexOf(r); + if (idx < 0) { + references.add(r); + idx = references.indexOf(r); + } + } } if (idx >= 0) { Reference r = references.get(idx); diff --git a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java index 6f3a808..779192a 100644 --- a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java +++ b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java @@ -201,7 +201,7 @@ public void shrinkAll(Map> newToOldMethodExecutionMap) { List refs = getReferences(); List collectionReferences = collectCollectionReferences(refs); - List> collectionChains = collectCollectionChains(collectionReferences); + List> collectionChains = collectCollectionChains(collectionReferences, newToOldMethodExecutionMap); refs = replaceCollectionChains(refs, collectionChains); refs = replaceStaticObjectIds(refs); references = new HashSet<>(refs); // Convert to Set from List. @@ -237,7 +237,7 @@ return collectionRefs; } - private List> collectCollectionChains(List collectionReferences) { + private List> collectCollectionChains(List collectionReferences, Map> newToOldMethodExecutionMap) { // Collect follow references. List collectionRefs = new ArrayList<>(collectionReferences); // Create new instance of coping collectionReference. List> collectionChains = new ArrayList<>(); @@ -247,21 +247,30 @@ Reference ref = collectionRefs.get(i); String srcClassName = ref.getSrcClassName(); String srcObjId = ref.getSrcObjectId(); - boolean isFirstRef = true; - // If dstClassName matches "$[1-9]" and don't shrink References too much(JHotDrawTransform). - if (!ref.getDstClassName().matches(".*\\$[0-9]+.*")) { - for (int j = 0; j < collectionReferences.size(); j++) { - if (collectionReferences.indexOf(ref) != j) { - Reference compareRef = collectionReferences.get(j); - if (srcClassName.equals(compareRef.getDstClassName()) - && srcObjId.equals(compareRef.getDstObjectId())) { - isFirstRef = false; - break; - } - } - } + boolean isShrinked = false; + for (MethodExecution me: newToOldMethodExecutionMap.keySet()) { + if (srcObjId.equals(me.getThisObjId())) { + isShrinked = true; + break; + } } - if (isFirstRef) { + boolean isFirstRef = true; + if (isShrinked) { + // If dstClassName matches "$[1-9]" and don't shrink References too much(JHotDrawTransform). + if (!ref.getDstClassName().matches(".*\\$[0-9]+.*")) { + for (int j = 0; j < collectionReferences.size(); j++) { + if (collectionReferences.indexOf(ref) != j) { + Reference compareRef = collectionReferences.get(j); + if (srcClassName.equals(compareRef.getDstClassName()) + && srcObjId.equals(compareRef.getDstObjectId())) { + isFirstRef = false; + break; + } + } + } + } + } + if (isShrinked && isFirstRef) { List collectionChain = new ArrayList<>(); collectionChain.add(ref); collectionChains.add(collectionChain); diff --git a/src/org/ntlab/deltaViewer/CollaborationViewer.java b/src/org/ntlab/deltaViewer/CollaborationViewer.java index 4188f52..5080d9f 100644 --- a/src/org/ntlab/deltaViewer/CollaborationViewer.java +++ b/src/org/ntlab/deltaViewer/CollaborationViewer.java @@ -447,12 +447,23 @@ for (Alias alias: aliasCollector.getAliasList()) { if (alias.getAliasType() == Alias.AliasType.THIS) { if (!objectToVertexMap.containsKey(alias.getObjectId()) && alias.getMethodExecution().isStatic()) { - // When both of the calling and called method are static. + // When both of the calling and called methods are static. String thisObjId = alias.getObjectId(); String thisClassName = alias.getMethodExecution().getThisClassName(); mxICell thisObjVxCell = (mxICell) mxgraph.insertDeltaVertex(getMxDefaultParent(), thisObjId, thisClassName, 0, 0, objVxWid, ObjVxHt, "fillColor=white"); //creates a white vertex. objectToVertexMap.put(thisObjId, new ObjectVertex(thisClassName, thisObjVxCell, 0, 0)); } + } else if (alias.getAliasType() == Alias.AliasType.FORMAL_PARAMETER) { + String thisClassName = alias.getMethodExecution().getThisClassName(); + String thisObjId = alias.getMethodExecution().getThisObjId(); + if (thisObjId.matches("0")) { + thisObjId += ":" + thisClassName; + } + if (!objectToVertexMap.containsKey(thisObjId)) { + // When the called method is static. + mxICell vertex = (mxICell) mxgraph.insertDeltaVertex(getMxDefaultParent(), thisObjId, thisClassName, 0, 0, objVxWid, ObjVxHt, "fillColor=white"); //creates a white vertex. + objectToVertexMap.put(thisObjId, new ObjectVertex(thisClassName, vertex, 0, 0)); + } } } } finally { @@ -565,7 +576,7 @@ } - if (srcClassName != null && fieldName != null && !edgeMap.containsKey(srcClassName + "." + fieldName)) { + if (srcClassName != null && fieldName != null && !edgeMap.containsKey(curAliasObjId + "." + fieldName)) { // Judge AliasList contains relatedPoint. (If contains not to create edge.) if (rpIndex < relatedPoints.size() - 1) { TracePoint rp = relatedPoints.get(rpIndex); @@ -590,7 +601,9 @@ } else { edgeCell = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldName, fieldName, srcObjVxCell, dstObjVxCell); } - edgeMap.put(srcClassName + "." + fieldName, new Edge(fieldName, TypeName.Reference, edgeCell)); + edgeMap.put(curAliasObjId + "." + fieldName, new Edge(fieldName, TypeName.Reference, edgeCell)); + } else { + edgeMap.put(curAliasObjId + "." + fieldName, new Edge(fieldName, TypeName.PreReference, curAliasObjId, nextAliasObjId)); } } finally { mxgraph.getModel().endUpdate(); diff --git a/src/org/ntlab/deltaViewer/DeltaViewer.java b/src/org/ntlab/deltaViewer/DeltaViewer.java index 487c974..0e214b9 100644 --- a/src/org/ntlab/deltaViewer/DeltaViewer.java +++ b/src/org/ntlab/deltaViewer/DeltaViewer.java @@ -585,7 +585,7 @@ System.out.println("ARRAY " + srcClassName + "(" + curAlias.getObjectId() + ") -> " + "(" + nextAlias.getObjectId() + "), " + fieldName); } } - if (srcClassName != null && fieldName != null && srcClassName != null && !edgeMap.containsKey(srcClassName + "." + fieldName)) { + if (srcClassName != null && fieldName != null && srcClassName != null && !edgeMap.containsKey(curAlias.getObjectId() + "." + fieldName)) { // Add a vertex to the graph in a transactional fashion. The vertex is actually a 'cell' in jgraphx terminology. mxgraph.getModel().beginUpdate(); try { @@ -595,9 +595,7 @@ System.out.println("makeEdgeObject: " + fieldName + ", " + srcClassName + " (" + srcCell.hashCode() + "), " + " (" + dstCell.hashCode() + ")"/* + ", " + dstClassName*/); // BUG:NullPointerException Object edge = mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldName, fieldName, srcCell, dstCell); - Point2D absPtSrcCell = getAbsolutePointforCell((mxICell)srcCell); - Point2D absPtDstCell = getAbsolutePointforCell((mxICell)dstCell); - edgeMap.put(srcClassName + "." + fieldName, new Edge(fieldName, TypeName.Reference, edge)); + edgeMap.put(curAlias.getObjectId() + "." + fieldName, new Edge(fieldName, TypeName.Reference, edge)); } } finally { mxgraph.getModel().endUpdate(); diff --git a/src/org/ntlab/deltaViewer/Edge.java b/src/org/ntlab/deltaViewer/Edge.java index bcc3c95..e340f72 100644 --- a/src/org/ntlab/deltaViewer/Edge.java +++ b/src/org/ntlab/deltaViewer/Edge.java @@ -8,9 +8,12 @@ public class Edge { String label; TypeName typeName; - Object cell; + Object cell; // edge cell + String srcObjId; // source object id to create the edge later + String dstObjId; // destination object id to create the edge later protected enum TypeName { + PreReference, // object will be referred later Reference, // object reference Create, // create object reference Call // method call @@ -26,6 +29,13 @@ this.typeName = typeName; this.cell = cell; } + + public Edge(String label, TypeName typeName, String srcObjId, String dstObjId) { + this.label = label; + this.typeName = typeName; + this.srcObjId = srcObjId; + this.dstObjId = dstObjId; + } public String getLabel() { return label; @@ -51,4 +61,19 @@ this.cell = cell; } + public String getSrcObjId() { + return srcObjId; + } + + public void setSrcObjId(String srcObjId) { + this.srcObjId = srcObjId; + } + + public String getDstObjId() { + return dstObjId; + } + + public void setDstObjId(String dstObjId) { + this.dstObjId = dstObjId; + } } diff --git a/src/org/ntlab/deltaViewer/MagnetRONViewer.java b/src/org/ntlab/deltaViewer/MagnetRONViewer.java index 24fd78e..efdfd11 100644 --- a/src/org/ntlab/deltaViewer/MagnetRONViewer.java +++ b/src/org/ntlab/deltaViewer/MagnetRONViewer.java @@ -269,7 +269,22 @@ "fillColor=white"); objVx.setCell(objVxCell); mxICell edgeCell = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldName, null, srcObjVxCell, objVxCell); - edgeMap.put(methodExec.getThisClassName() + "." + fieldName, new Edge(fieldName, TypeName.Create, edgeCell)); + edgeMap.put(alias.getObjectId() + "." + fieldName, new Edge(fieldName, TypeName.Create, edgeCell)); + for (String edgeKey: edgeMap.keySet()) { + Edge edge = edgeMap.get(edgeKey); + if (edgeKey.startsWith(alias.getObjectId() + ".") && edge.getTypeName() == Edge.TypeName.PreReference) { + mxICell dstCell = (mxICell) objectToVertexMap.get(edge.getDstObjId()).getCell(); + String fieldNames[] = edgeKey.split("."); + mxICell edgeCell2 = null; + if (fieldNames.length < 2) { + edgeCell2 = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), "", "", objVxCell, dstCell); + } else { + edgeCell2 = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldNames[1], fieldNames[1], objVxCell, dstCell); + } + edge.setTypeName(Edge.TypeName.Reference); + edge.setCell(edgeCell2); + } + } update(); } finally { mxgraph.getModel().endUpdate(); @@ -321,7 +336,22 @@ "fillColor=white"); objVx.setCell(objVxCell); mxICell edgeCell = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldName, null, srcObjVxCell, objVxCell); - edgeMap.put(methodExec.getThisClassName() + "." + fieldName, new Edge(fieldName, TypeName.Create, edgeCell)); + edgeMap.put(alias.getObjectId() + "." + fieldName, new Edge(fieldName, TypeName.Create, edgeCell)); + for (String edgeKey: edgeMap.keySet()) { + Edge edge = edgeMap.get(edgeKey); + if (edgeKey.startsWith(alias.getObjectId() + ".") && edge.getTypeName() == Edge.TypeName.PreReference) { + mxICell dstCell = (mxICell) objectToVertexMap.get(edge.getDstObjId()).getCell(); + String fieldNames[] = edgeKey.split("."); + mxICell edgeCell2 = null; + if (fieldNames.length < 2) { + edgeCell2 = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), "", "", objVxCell, dstCell); + } else { + edgeCell2 = (mxICell) mxgraph.insertDeltaEdge(getMxDefaultParent(), fieldNames[1], fieldNames[1], objVxCell, dstCell); + } + edge.setTypeName(Edge.TypeName.Reference); + edge.setCell(edgeCell2); + } + } update(); } finally { mxgraph.getModel().endUpdate(); @@ -367,7 +397,7 @@ srcObjVxCell, dstObjVxCell); edgeCell.setStyle("strokeColor=red;"); // mxgraph.orderCells(true, new Object[] {edge}); - edgeMap.put(fieldUpdateStatement.getFieldName(), new Edge(fieldName, TypeName.Reference, edgeCell)); + edgeMap.put(fieldUpdateStatement.getContainerObjId(), new Edge(fieldName, TypeName.Reference, edgeCell)); } finally { mxgraph.getModel().endUpdate(); } @@ -924,11 +954,10 @@ methodSignature = formatMethodSignature(methodSignature, methodExecution.getThisClassName()); } - // TODO: Confirm why is the following code needed? - if (methodExecution.isStatic() && !objectId.startsWith("0")) { - objectId = methodExecution.getCallerMethodExecution().getThisObjId(); + if (methodExecution.isStatic() && !objectId.startsWith("0")) { // Check the object id is a formal parameter's one. + objectId = methodExecution.getThisObjId(); if (objectId.matches("0")) { - objectId += ":" + methodExecution.getCallerMethodExecution().getThisClassName(); + objectId += ":" + methodExecution.getThisClassName(); } }