diff --git a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java index 77852c3..ff118a1 100644 --- a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java +++ b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java @@ -5,12 +5,15 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.stream.Collectors; import org.ntlab.deltaExtractor.ExtractedStructure; 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; /** @@ -123,12 +126,13 @@ return sortedTpList; } - public void shrinkAll() { + public void shrinkAll(Map> newToOldMethodExecutionMap) { List refs = getReferences(); List collectionReferences = collectCollectionReferences(refs); List> collectionChains = collectCollectionChains(collectionReferences); refs = replaceCollectionChains(refs, collectionChains); - references = new HashSet<>(refs); + references = new HashSet<>(refs); // Convert to Set from List. + relatedPoints = replaceRelatedPoints(relatedPoints, newToOldMethodExecutionMap); // For debug. System.out.println("collectionReferences: "); @@ -171,9 +175,9 @@ String srcClassName = ref.getSrcClassName(); String srcObjId = ref.getSrcObjectId(); boolean isFirstRef = true; - for (int j = 0; j < collectionRefs.size(); j++) { - if (i != j) { - Reference compareRef = collectionRefs.get(j); + 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; @@ -238,7 +242,32 @@ replacedReferences.add(newRef); // Add new reference. } return replacedReferences; - + } + + /** + * Replace calledMethodExec in relatedPoints to newMethodExec. + * @param relatedPoints + * @param newToOldMethodExecutionMap + * @return Replaced related points. + */ + private List replaceRelatedPoints(List relatedPoints, Map> newToOldMethodExecutionMap) { + List replacedRp = new ArrayList<>(relatedPoints); + for (TracePoint rp: replacedRp) { + Statement st = rp.getStatement(); + if (st instanceof MethodInvocation) { + MethodInvocation methodInv = (MethodInvocation)st; + MethodExecution calledMethodExec = methodInv.getCalledMethodExecution(); + for (Entry> entry: newToOldMethodExecutionMap.entrySet()) { + MethodExecution newMethodExec = entry.getKey(); + Set oldMethodExecSet = entry.getValue(); + if (oldMethodExecSet.contains(calledMethodExec)) { + methodInv.setCalledMethodExecution(newMethodExec); + } + } + + } + } + return replacedRp; } } diff --git a/src/org/ntlab/deltaViewer/DeltaAliasCollector.java b/src/org/ntlab/deltaViewer/DeltaAliasCollector.java index 9ec9be5..ae05ff4 100644 --- a/src/org/ntlab/deltaViewer/DeltaAliasCollector.java +++ b/src/org/ntlab/deltaViewer/DeltaAliasCollector.java @@ -1,7 +1,11 @@ package org.ntlab.deltaViewer; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import org.ntlab.deltaExtractor.Alias; import org.ntlab.deltaExtractor.Alias.AliasType; @@ -78,27 +82,30 @@ } - public void shrink() { + public Map> shrink() { + List oldAliasList = new ArrayList<>(aliasList); List standardMethodInvocations = collectStandardMethodInvocations(aliasList); - List> invocationChains = collectInvocatoinChains(standardMethodInvocations); - aliasList = replaceInvocatoinChains(aliasList, invocationChains); + List> invocationChains = collectInvocationChains(standardMethodInvocations); + aliasList = replaceInvocationChains(aliasList, invocationChains); + Map> newToOldMethodExecMap = collectNewToOldMethodExecutionMap(oldAliasList, aliasList); // for debug. System.out.println("standardMethodInvocations: "); for (Alias alias: standardMethodInvocations) { System.out.println(alias.getAliasType() + ":: " + alias.getObjectId() + ": " + alias.getMethodSignature()); } - System.out.println("invocatoinChains: "); + System.out.println("invocationChains: "); for (int i = 0; i < invocationChains.size(); i++) { System.out.println("i = " + i); for (Alias alias: invocationChains.get(i)) { System.out.println("\t" + alias.getAliasType() + ":: " + alias.getObjectId() + ": " + alias.getMethodSignature()); } } - System.out.println("replaceInvocatoinChains: "); + System.out.println("replaceInvocationChains: "); for (Alias alias: aliasList) { System.out.println(alias.getObjectId() + ": " + alias.getMethodSignature() + " l." + alias.getLineNo() + " :: " + alias.getAliasType().toString()); } + return newToOldMethodExecMap; } private List collectStandardMethodInvocations(List aliasList) { @@ -137,8 +144,9 @@ return standardMethodInvocations; } - private List> collectInvocatoinChains(List standardMethodInvocations) { + private List> collectInvocationChains(List standardMethodInvocations) { List> invocationChains = new ArrayList<>(); + if (standardMethodInvocations.isEmpty()) return invocationChains; List invChainsIdx = new ArrayList<>(); // Compare whether same callerMethodExecution. MethodExecution compareMethodExec = null; @@ -175,13 +183,6 @@ invChainsIdx.clear(); } } - System.out.println("invocatoinChains: "); - for (int i = 0; i < invocationChains.size(); i++) { - System.out.println("i = " + i); - for (Alias alias: invocationChains.get(i)) { - System.out.println("\t" + alias.getAliasType() + ": " + alias.getObjectId() + ", " + alias.getMethodSignature()); - } - } // Compare whether same objectId from RETURN_VALUE to THIS. int i = 0; @@ -219,8 +220,9 @@ return invocationChains; } - private List replaceInvocatoinChains(List aliasList, List> invocationChains) { + private List replaceInvocationChains(List aliasList, List> invocationChains) { List replacedAliasList = new ArrayList<>(aliasList); + if (invocationChains.isEmpty()) return replacedAliasList; for (List invChain: invocationChains) { int firstIdx = replacedAliasList.indexOf(invChain.get(0)); // RECEIVER int secondIdx = replacedAliasList.indexOf(invChain.get(1)); // THIS @@ -253,6 +255,7 @@ MethodExecution newCalledMethodExec = new MethodExecution(signatureChains, callerSideSignature, thisClassName, thisObjId, false, false, enterTime); newCalledMethodExec.setCollectionType(true); newCalledMethodExec.setExitTime(exitTime); + newCalledMethodExec.setReturnValue(oldReturnValAlias.getOccurrencePoint().getMethodExecution().getReturnValue()); TracePoint newThisTp = new TracePoint(newCalledMethodExec, -1); Alias newThisAlias = new Alias(AliasType.THIS, 0, thisObjId, newThisTp.duplicate()); @@ -272,7 +275,7 @@ // Create new alias for METHOD_INVOCATION. Alias newMethodInvAlias = new Alias(AliasType.METHOD_INVOCATION, 0, returnValObjId, receiverTp.duplicate()); - /* Replace InvocatoinChains */ + /* Replace InvocationChains */ // Remove invocationChains from aliasList. for (int i = 1; i < invChain.size(); i++) { // Except first alias of THIS. Alias invAlias = invChain.get(i); @@ -291,4 +294,32 @@ return replacedAliasList; } + /** + * Collect methodExecutions for Alias that are not equal in oldAliasList and newAliasList. + * @param oldAliasList + * @param newAliasList + * @return One-to-many, Key is new methodExecution in newAliasList, Values are set of old methodExecutions in oldAlias replaced by newAlias. + */ + private Map> collectNewToOldMethodExecutionMap(List oldAliasList, List newAliasList) { + Map> newToOldMethodExecMap = new HashMap<>(); + int oldIdx = 0, newIdx = 0; + for (oldIdx = 0; oldIdx < oldAliasList.size(); oldIdx++) { + Alias oldAlias = oldAliasList.get(oldIdx); + Alias newAlias = newAliasList.get(newIdx); + if (oldAlias.equals(newAlias)) { + newIdx++; + } else { + MethodExecution oldMethodExec = oldAlias.getMethodExecution(); + MethodExecution newMethodExec = newAlias.getMethodExecution(); + if (!newToOldMethodExecMap.containsKey(newMethodExec)) { + newToOldMethodExecMap.put(newMethodExec, new HashSet<>()); + newToOldMethodExecMap.get(newMethodExec).add(oldMethodExec); + } else { + newToOldMethodExecMap.get(newMethodExec).add(oldMethodExec); + } + } + } + return newToOldMethodExecMap; + } + } diff --git a/src/org/ntlab/deltaViewer/MagnetRONFrame.java b/src/org/ntlab/deltaViewer/MagnetRONFrame.java index 185abdd..79d4a24 100644 --- a/src/org/ntlab/deltaViewer/MagnetRONFrame.java +++ b/src/org/ntlab/deltaViewer/MagnetRONFrame.java @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.Map.Entry; import javax.swing.JFrame; @@ -137,10 +138,11 @@ } public Map.Entry extractMulti(List keys) { - CollaborationObjectCallGraph cocg = null; - CollaborationAliasCollector cac = null; trace = null; s = null; + CollaborationObjectCallGraph cocg = null; + CollaborationAliasCollector cac = null; + Map> newToOldMethodExecMap = new HashMap<>(); for(String key: keys) { int index = 0; @@ -164,12 +166,16 @@ } else { cocg.merge(extracted.getKey()); } + IAliasCollector ac = extracted.getValue(); + DeltaAliasCollector dac = (DeltaAliasCollector) ac; + newToOldMethodExecMap.putAll(dac.shrink()); if (cac == null) { - cac = new CollaborationAliasCollector(extracted.getValue()); + cac = new CollaborationAliasCollector(dac); } else { - cac.merge(extracted.getValue()); + cac.merge(dac); } } + cocg.shrinkAll(newToOldMethodExecMap); return new AbstractMap.SimpleEntry(cocg, cac); } @@ -435,7 +441,7 @@ @Override public void startAnimation() { - if (animationThread != null) { + if (animationThread == null) { animationThread = new Thread() { public void run() { // Build a frame, create a graph, and add the graph to the frame so you can actually see the graph. diff --git a/src/org/ntlab/deltaViewer/MagnetRONViewer.java b/src/org/ntlab/deltaViewer/MagnetRONViewer.java index 0339170..f54d8b4 100644 --- a/src/org/ntlab/deltaViewer/MagnetRONViewer.java +++ b/src/org/ntlab/deltaViewer/MagnetRONViewer.java @@ -1123,17 +1123,20 @@ } protected String formatMethodSignature(String methodSignature, String thisClassName) { + // TODO Modify algorithm formatMethodSignature(). // Step1 : split "(" - String[] methodSignatures = methodSignature.split("\\("); - methodSignature = methodSignatures[0]; +// String[] methodSignatures = methodSignature.split("\\("); + methodSignature = methodSignature.substring(0, methodSignature.lastIndexOf('(')); // Step2 : split " " - methodSignatures = methodSignature.split(" "); + String[] methodSignatures = methodSignature.split(" "); String tmpMethodSignature = methodSignatures[methodSignatures.length-1]; - // Step2 : split "." + // Step3 : split "." String[] thisClassNames = thisClassName.split("\\."); methodSignatures = tmpMethodSignature.split("\\."); StringBuffer sb = new StringBuffer(); int i = methodSignatures.length - 2; + int count = methodSignature.split("\\(").length - 1; + if (count > 0) i -= count; if (i >= 0 && !thisClassNames[thisClassNames.length - 1].equals(methodSignatures[i])) { if (thisClassNames[thisClassNames.length - 1].equals(methodSignatures[i + 1])) i += 1; sb.append(methodSignatures[i]); diff --git a/src/tests/CollaborationObjectCallGraphTest.java b/src/tests/CollaborationObjectCallGraphTest.java index ccce337..6b1662a 100644 --- a/src/tests/CollaborationObjectCallGraphTest.java +++ b/src/tests/CollaborationObjectCallGraphTest.java @@ -3,13 +3,17 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.junit.jupiter.api.Test; import org.ntlab.deltaExtractor.ExtractedStructure; import org.ntlab.deltaExtractor.IAliasCollector; +import org.ntlab.deltaViewer.CollaborationAliasCollector; import org.ntlab.deltaViewer.CollaborationObjectCallGraph; +import org.ntlab.deltaViewer.DeltaAliasCollector; import org.ntlab.trace.FieldUpdate; import org.ntlab.trace.MethodExecution; import org.ntlab.trace.MethodInvocation; @@ -24,12 +28,27 @@ // Change Here! // String key = "getterOverlap"; // String key = "setterOverlap"; - String key = "JHotDrawSelect"; + String key = "ArgoUMLDelete"; +// String key = "JHotDrawSelect"; MagnetRONFrameTest magnetRONFrame = new MagnetRONFrameTest(); Map extractedMultipleDeltas = magnetRONFrame.extractMultipleDeltas(key); List eList = new ArrayList<>(extractedMultipleDeltas.keySet()); List dacList = new ArrayList<>(extractedMultipleDeltas.values()); + CollaborationAliasCollector cac = null; + Map> newToOldMethodExecMap = new HashMap<>(); + for (IAliasCollector ac: dacList) { + if (ac instanceof DeltaAliasCollector) { + DeltaAliasCollector dac = (DeltaAliasCollector) ac; + newToOldMethodExecMap.putAll(dac.shrink()); + if (cac == null) { + cac = new CollaborationAliasCollector(dac); + } else { + cac.merge(dac); + } + } + } + CollaborationObjectCallGraph cocg = null; for (ExtractedStructure e: eList) { if (cocg == null) { @@ -91,13 +110,13 @@ assertTrue(cocg.getReferences().containsAll(e.getDelta().getDstSide())); assertTrue(cocg.getRelatedPoints().contains(e.getRelatedTracePoint())); } - testShrinkAll(true, cocg); + testShrinkAll(true, cocg, newToOldMethodExecMap); // Replaced References and RelatedPoints. } @Test - private void testShrinkAll(boolean isShrink, CollaborationObjectCallGraph cocg) { + private void testShrinkAll(boolean isShrink, CollaborationObjectCallGraph cocg, Map> newToOldMethodExecMap) { if (isShrink) { - cocg.shrinkAll(); + cocg.shrinkAll(newToOldMethodExecMap); } } }