package neo4j.traversals.readWriteDB; import java.util.LinkedList; import java.util.List; import misc.Pair; import neo4j.readWriteDB.Neo4JDBInterface; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.NotFoundException; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.index.IndexHits; import databaseNodes.EdgeTypes; import databaseNodes.NodeKeys; import ddg.DataDependenceGraph.DDG; public class Traversals { public static IndexHits<Node> getStatementsForFunction(Node funcNode) { String query = String.format("%s:True AND %s:%d", NodeKeys.IS_CFG_NODE, NodeKeys.FUNCTION_ID, funcNode.getId()); return Neo4JDBInterface.queryIndex(query); } public static List<Pair<Long, String>> getSymbolsDefinedByStatement( Long statementId) { Node node = Neo4JDBInterface.getNodeById(statementId); return getIdAndCodeOfChildrenConnectedBy(node, "DEF"); } public static List<Pair<Long, String>> getSymbolsUsedByStatement( Long statementId) { Node node = Neo4JDBInterface.getNodeById(statementId); return getIdAndCodeOfChildrenConnectedBy(node, "USE"); } public static List<String> getCodeOfChildrenConnectedBy(Node node, String edgeType) { List<String> retval = new LinkedList<String>(); List<Node> children = getChildrenConnectedBy(node, edgeType); for (Node childNode : children) { String childCode = childNode.getProperty(NodeKeys.CODE).toString(); retval.add(childCode); } return retval; } public static List<Pair<Long, String>> getIdAndCodeOfChildrenConnectedBy( Node node, String edgeType) { List<Pair<Long, String>> retval = new LinkedList<Pair<Long, String>>(); List<Node> children = getChildrenConnectedBy(node, edgeType); for (Node childNode : children) { String childCode = childNode.getProperty(NodeKeys.CODE).toString(); Pair<Long, String> pair = new Pair<Long, String>(childNode.getId(), childCode); retval.add(pair); } return retval; } public static List<Node> getChildrenConnectedBy(Node node, String edgeType) { List<Node> retval = new LinkedList<Node>(); long nodeId = node.getId(); Iterable<Relationship> rels = node.getRelationships(); for (Relationship rel : rels) { if (!rel.getType().name().equals(edgeType)) continue; Node childNode = rel.getEndNode(); if (childNode.getId() == nodeId) continue; retval.add(childNode); } return retval; } public static List<Node> getParentsConnectedBy(Node node, String edgeType) { List<Node> retval = new LinkedList<Node>(); long nodeId = node.getId(); Iterable<Relationship> rels = node.getRelationships(); for (Relationship rel : rels) { if (!rel.getType().name().equals(edgeType)) continue; Node parentNode = rel.getStartNode(); if (parentNode.getId() == nodeId) continue; retval.add(parentNode); } return retval; } public static List<Node> getCallsTo(String source) { List<Node> retval = new LinkedList<Node>(); String query = String.format("%s:CallExpression AND %s:%s" + "*", NodeKeys.TYPE, NodeKeys.CODE, source); IndexHits<Node> hits = Neo4JDBInterface.queryIndex(query); for (Node n : hits) { if (n.getProperty(NodeKeys.CODE).toString() .startsWith(source + " ")) retval.add(n); } return retval; } public static List<Node> getCallsToForFunction(String source, long functionId) { List<Node> retval = new LinkedList<Node>(); String query = String.format("%s:CallExpression AND %s:%d AND %s:%s" + "*", NodeKeys.TYPE, NodeKeys.FUNCTION_ID, functionId, NodeKeys.CODE, source); IndexHits<Node> hits = Neo4JDBInterface.queryIndex(query); for (Node n : hits) { if (n.getProperty(NodeKeys.CODE).toString() .startsWith(source + " ")) retval.add(n); } return retval; } public static DDG getDDGForFunction(Node funcNode) { DDG retval = new DDG(); for (Node statement : Traversals.getStatementsForFunction(funcNode)) { Iterable<Relationship> rels = statement .getRelationships(Direction.OUTGOING); long srcId = statement.getId(); for (Relationship rel : rels) { if (!rel.getType().toString().equals(EdgeTypes.REACHES)) continue; long dstId = rel.getEndNode().getId(); String symbol = rel.getProperty("var").toString(); retval.add(srcId, dstId, symbol); } } return retval; } // The two following functions are somewhat disgraceful // but should work for now. public static Node getStatementForASTNode(Node node) { Node n = node; Node parent = node; while (true) { try { Object property = n.getProperty(NodeKeys.IS_CFG_NODE); return n; } catch (NotFoundException ex) { } Iterable<Relationship> rels = n .getRelationships(Direction.INCOMING); for (Relationship rel : rels) { parent = rel.getStartNode(); break; } if (n == parent) return null; n = parent; } } public static String getNthArgCodeOfCall(Node callNode, int n) { String nStr = String.format("%d", n); Iterable<Relationship> rels = callNode .getRelationships(Direction.OUTGOING); for (Relationship rel : rels) { if (!rel.getType().toString().equals(EdgeTypes.IS_AST_PARENT)) continue; Node endNode = rel.getEndNode(); String childNum; try { childNum = (String) endNode.getProperty(NodeKeys.CHILD_NUMBER); } catch (RuntimeException ex) { childNum = "0"; } if (childNum.equals("1")) { // found argument list Node argList = rel.getEndNode(); Iterable<Relationship> rels2 = argList .getRelationships(Direction.OUTGOING); for (Relationship rel2 : rels2) { if (!rel2.getType().toString() .equals(EdgeTypes.IS_AST_PARENT)) continue; String childNum2; try { childNum2 = (String) rel2.getEndNode().getProperty( NodeKeys.CHILD_NUMBER); } catch (RuntimeException ex) { childNum2 = "0"; } if (childNum2.equals(nStr)) return rel2.getEndNode().getProperty(NodeKeys.CODE) .toString(); } } } return null; } public static Long getFunctionIdFromASTNode(Node astNode) { return Long.valueOf(astNode.getProperty(NodeKeys.FUNCTION_ID) .toString()); } public static IndexHits<Node> getFunctionsByName(String functionName) { return Neo4JDBInterface.queryIndex(NodeKeys.NAME + ":" + functionName); } public static Node getASTForStatement(Node statement) { return statement; } public static String getNodeType(Long nodeId) { Node node = Neo4JDBInterface.getNodeById(nodeId); return node.getProperty(NodeKeys.TYPE).toString(); } public static String getCalleeFromCall(Long nodeId) { Node node = Neo4JDBInterface.getNodeById(nodeId); Iterable<Relationship> rels = node.getRelationships(); for (Relationship rel : rels) { if (!rel.getType().name().equals(EdgeTypes.IS_AST_PARENT)) continue; Node endNode = rel.getEndNode(); if (endNode.getId() == node.getId()) continue; try { String childNumStr = (String) endNode .getProperty(NodeKeys.CHILD_NUMBER); if (childNumStr.equals("0")) return endNode.getProperty(NodeKeys.CODE).toString(); } catch (RuntimeException ex) { return endNode.getProperty(NodeKeys.CODE).toString(); } } return ""; } public static String getNodeCode(long nodeId) { Node node = Neo4JDBInterface.getNodeById(nodeId); return node.getProperty(NodeKeys.CODE).toString(); } public static String getOperatorCode(long nodeId) { Node node = Neo4JDBInterface.getNodeById(nodeId); return node.getProperty(NodeKeys.OPERATOR).toString(); } public static int getNodeChildNum(long nodeId) { Node node = Neo4JDBInterface.getNodeById(nodeId); String childNumStr = (String) node.getProperty(NodeKeys.CHILD_NUMBER, null); if (childNumStr == null) return 0; return Integer.parseInt(childNumStr); } }