diff --git a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java index ed4bc60..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; /** @@ -122,4 +125,149 @@ }).collect(Collectors.toList()); return sortedTpList; } + + public void shrinkAll(Map> newToOldMethodExecutionMap) { + List refs = getReferences(); + List collectionReferences = collectCollectionReferences(refs); + List> collectionChains = collectCollectionChains(collectionReferences); + refs = replaceCollectionChains(refs, collectionChains); + references = new HashSet<>(refs); // Convert to Set from List. + relatedPoints = replaceRelatedPoints(relatedPoints, newToOldMethodExecutionMap); + + // For debug. + System.out.println("collectionReferences: "); + for (Reference ref: collectionReferences) { + System.out.println("\t" + ref.getSrcClassName() + "(" + ref.getSrcObjectId() + ")" + " -> " + ref.getDstClassName() + "(" + ref.getDstObjectId() + "): " + ref.isCollection()); + } + System.out.println("collectionChains: "); + for (int i = 0; i < collectionChains.size(); i++) { + List CollectionChain = collectionChains.get(i); + System.out.println("i = " + i); + for (Reference ref: CollectionChain) { + System.out.println("\t" + ref.getSrcClassName() + "(" + ref.getSrcObjectId() + ")" + " -> " + ref.getDstClassName() + "(" + ref.getDstObjectId() + "): " + ref.isCollection()); + } + } + System.out.println("replaceCollectionChains: "); + for (Reference ref: references) { + System.out.println("\t" + ref.getSrcClassName() + "(" + ref.getSrcObjectId() + ")" + " -> " + ref.getDstClassName() + "(" + ref.getDstObjectId() + "): " + ref.isCollection()); + } + } + + private List collectCollectionReferences(List references) { + // Collect references that are Collection. + List collectionRefs = new ArrayList<>(); + for (Reference ref: references) { + if (ref.isCollection()) { + collectionRefs.add(ref); + } + } + return collectionRefs; + } + + private List> collectCollectionChains(List collectionReferences) { + // Collect follow references. + List collectionRefs = new ArrayList<>(collectionReferences); // Create new instance of coping collectionReference. + List> collectionChains = new ArrayList<>(); + // Search first reference. + int i = 0; + while (i < collectionRefs.size()) { + Reference ref = collectionRefs.get(i); + String srcClassName = ref.getSrcClassName(); + String srcObjId = ref.getSrcObjectId(); + boolean isFirstRef = true; + 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 (isFirstRef) { + List collectionChain = new ArrayList<>(); + collectionChain.add(ref); + collectionChains.add(collectionChain); + collectionRefs.remove(i); + } else { + i++; + } + } + + // Search references follow first reference. + for (i = 0; i < collectionChains.size(); i++) { + List collectionChain = collectionChains.get(i); + int j = 0; + while (j < collectionChain.size()) { + Reference ref = collectionChain.get(j); + String dstClassName = ref.getDstClassName(); + String dstObjId = ref.getDstObjectId(); + j++; + for (int k = 0; k < collectionRefs.size(); k++) { + Reference compareRef = collectionRefs.get(k); + if (dstClassName.equals(compareRef.getSrcClassName()) + && dstObjId.equals(compareRef.getSrcObjectId())) { + collectionChain.add(compareRef); + collectionRefs.remove(k); + break; + } + } + } + if (collectionChain.size() == 1) { + collectionChains.remove(i); + i--; + } + } + return collectionChains; + } + + private List replaceCollectionChains(List references, List> collectionChains) { + // Replace to shrink Reference in references. + List replacedReferences = new ArrayList<>(references); + for (List collectionChain: collectionChains) { + // Create shrink new reference. + Reference firstRef = collectionChain.get(0); + Reference lastRef = collectionChain.get(collectionChain.size() - 1); + Reference newRef = new Reference(firstRef.getSrcObjectId(), lastRef.getDstObjectId(), firstRef.getSrcClassName(), lastRef.getDstClassName()); + newRef.setCollection(true); + + // Remove collectionChains from references. + for (int i = 0; i < collectionChain.size(); i++) { + Reference ref = collectionChain.get(i); + int refIdx = replacedReferences.indexOf(ref); // Get index of collection reference in references. + if (refIdx != - 1) replacedReferences.remove(refIdx); + else System.out.println("Failed to remove collection reference in references..."); + } + 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; + } + }