package org.lrg.outcode.eclipse.handlers; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.eclipse.core.commands.ExecutionException; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IViewPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.json.JSONArray; import org.json.JSONObject; import org.lrg.outcode.IHindsight; import org.lrg.outcode.activator.GraphDB; import org.lrg.outcode.builder.RelTypes; import org.lrg.outcode.builder.db.GraphDatasource; import org.lrg.outcode.views.Hindsight; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Label; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.Transaction; public class EntityAccessesEvolution { class Indexer { Integer index = 0; String commit = ""; } class RelationHistory { private String entityId; private String fromFile; private HashMap<Integer, String> rels; private Indexer i; public RelationHistory(String attrId, String fromFile, Indexer i) { this.entityId = attrId; this.fromFile = fromFile; this.rels = new HashMap<>(); this.i = i; } public void add(int index, String id) { rels.put(index, id); } public JSONObject toJson() { JSONObject result = new JSONObject(); result.put("entityId", entityId); result.put("filePath", fromFile); JSONArray rels = new JSONArray(); for (int i = 0; i < this.i.index; i++) { rels.put(i, this.rels.get(i)); } result.put("rels", rels); return result; } @Override public String toString() { return toJson().toString(2); } } private GraphDatasource db = GraphDatasource.INSTANCE; public Object execute(ICompilationUnit unit) throws ExecutionException { IJavaElement selected; Transaction beginTx = null; try { if (unit.getTypes().length > 0) { selected = unit.getTypes()[0]; } else { return null; } System.out.println("selected = " + selected); if (selected.getElementType() == IJavaElement.TYPE) { beginTx = GraphDB.instance.getDB().beginTx(); Node findFirstNodeForElementID = db.findFirsNodeForElementID(selected); JSONArray iJavaElementNamesArray = new JSONArray(); JSONObject showAccessesHistoryForClass = new JSONObject(); showAccessesHistoryForClass.put("msg", "showAccessesHistoryForClass"); if (findFirstNodeForElementID != null) { Node next = findFirstNodeForElementID; // the list of all accesses ever, it's a treemap because we care about the order Map<String, RelationHistory> data = new TreeMap<>(); Map<String, Integer> accessToArrayIndex = new TreeMap<String, Integer>(); final Indexer i = new Indexer(); final String portableString = unit.getResource().getProjectRelativePath().toPortableString(); String commitID = null; String prev_commit = null; do { JSONObject jsonObject = new JSONObject(); if (commitID != null) prev_commit = commitID.toString(); // jsonObject.put("prev_" + IHindsight.COMMITID, commitID); commitID = next.getProperty(IHindsight.COMMITID).toString(); i.commit = prev_commit + "-" + commitID; jsonObject.put(IHindsight.COMMITID, commitID); final Node c = next; // go through all methods, get all accesses and print them List<Integer> currentNodeAccesses = new ArrayList<Integer>();// contains a list of indexes from the map of all accesses ever Iterable<Relationship> containedMethods = next.getRelationships(RelTypes.CONTAINS, Direction.OUTGOING); Stream<Relationship> stream = StreamSupport.stream(containedMethods.spliterator(), false); stream.map(contains -> contains.getEndNode()).filter(method -> method.hasLabel(Label.label("Method"))).forEach(method -> { Stream<Relationship> accessedFields = StreamSupport.stream(method.getRelationships(RelTypes.ACCESSES, Direction.OUTGOING).spliterator(), false); accessedFields.map(access -> access.getEndNode()) .filter(attr -> !attr.getRelationships(RelTypes.PARENT, Direction.OUTGOING).iterator().hasNext() || !(attr.getRelationships(RelTypes.PARENT, Direction.OUTGOING).iterator().next().getEndNode().equals(c))).forEach((attr) -> { Object attrId = attr.getProperty(IHindsight.ID); if (data.containsKey(attrId)) { data.get(attrId).add(i.index, i.commit); } else { data.put(attrId.toString(), new RelationHistory(attrId.toString(), portableString, i)); data.get(attrId).add(i.index, i.commit); } if (accessToArrayIndex.containsKey(attrId)) { if (!currentNodeAccesses.contains(accessToArrayIndex.get(attrId))) currentNodeAccesses.add(accessToArrayIndex.get(attrId)); } else { int size = accessToArrayIndex.size(); if (!currentNodeAccesses.contains(size)) currentNodeAccesses.add(size); accessToArrayIndex.put(attrId.toString(), size); } }); }); next = findNextNode(next); i.index++; } while (next != null); accessToArrayIndex.entrySet().stream().sorted((o1, o2) -> o1.getValue().compareTo(o2.getValue())).forEach(entry -> { JSONObject accessedAttribute = new JSONObject(); accessedAttribute.put(entry.getValue().toString(), entry.getKey()); iJavaElementNamesArray.put(accessedAttribute); }); JSONArray dataArray = new JSONArray(); data.values().stream().sorted((v1, v2) -> { int result = v1.rels.keySet().stream().mapToInt(k -> k).min().getAsInt() - v2.rels.keySet().stream().mapToInt(k -> k).min().getAsInt(); if (result == 0) result = v2.rels.keySet().stream().mapToInt(k -> 1).sum() - v1.rels.keySet().stream().mapToInt(k -> 1).sum(); return result; }).forEach(v -> dataArray.put(v.toJson())); showAccessesHistoryForClass.put("history", dataArray); System.out.println("data " + dataArray); } if (PlatformUI.getWorkbench().getWorkbenchWindowCount() > 0) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { IViewPart showView; try { showView = PlatformUI.getWorkbench().getWorkbenchWindows()[0].getActivePage().showView(Hindsight.VIEW_ID); if (showView instanceof Hindsight) { Hindsight hindsight = (Hindsight) showView; String replaceAll = showAccessesHistoryForClass.toString(4).replaceAll("\"", "'"); System.out.println("send the message \n" + replaceAll); hindsight.sendMessage(replaceAll); } } catch (PartInitException e) { e.printStackTrace(); } } }); } beginTx.success(); } } catch (JavaModelException e) { e.printStackTrace(); } finally { if (beginTx != null) { beginTx.close(); } } return null; } private Node findNextNode(Node node) { Iterable<Relationship> toNext = node.getRelationships(RelTypes.NEXT, Direction.OUTGOING); if (toNext.iterator().hasNext()) return toNext.iterator().next().getEndNode(); return null; } }