From 3603461b26a25a0a13c4c98980b07925505c8696 Mon Sep 17 00:00:00 2001 From: Amr Morad Date: Tue, 19 May 2020 14:30:17 +0200 Subject: [PATCH 1/2] add the project code which contains the API for getting the graph from Neo4j datastore along with updating this graph --- .gitignore | 35 ++++ link-serv.iml | 85 +++++++++ linkserv.iml | 85 +++++++++ pom.xml | 98 ++++++++++ .../org/bibalex/linkserv/MainLinkServ.java | 27 +++ .../controllers/LinkServController.java | 52 ++++++ .../errors/OperationNotFoundException.java | 9 + .../linkserv/handlers/JSONHandler.java | 174 ++++++++++++++++++ .../linkserv/handlers/Neo4jHandler.java | 136 ++++++++++++++ .../linkserv/handlers/PropertiesHandler.java | 18 ++ .../handlers/WorkspaceNameHandler.java | 27 +++ .../org/bibalex/linkserv/models/Edge.java | 48 +++++ .../org/bibalex/linkserv/models/Node.java | 47 +++++ .../linkserv/services/LinkServService.java | 81 ++++++++ src/main/resources/application.properties | 11 ++ src/main/resources/config.properties | 29 +++ src/main/resources/log4j.properties | 14 ++ 17 files changed, 976 insertions(+) create mode 100644 .gitignore create mode 100644 link-serv.iml create mode 100644 linkserv.iml create mode 100644 pom.xml create mode 100644 src/main/java/org/bibalex/linkserv/MainLinkServ.java create mode 100644 src/main/java/org/bibalex/linkserv/controllers/LinkServController.java create mode 100644 src/main/java/org/bibalex/linkserv/errors/OperationNotFoundException.java create mode 100644 src/main/java/org/bibalex/linkserv/handlers/JSONHandler.java create mode 100644 src/main/java/org/bibalex/linkserv/handlers/Neo4jHandler.java create mode 100644 src/main/java/org/bibalex/linkserv/handlers/PropertiesHandler.java create mode 100644 src/main/java/org/bibalex/linkserv/handlers/WorkspaceNameHandler.java create mode 100644 src/main/java/org/bibalex/linkserv/models/Edge.java create mode 100644 src/main/java/org/bibalex/linkserv/models/Node.java create mode 100644 src/main/java/org/bibalex/linkserv/services/LinkServService.java create mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/config.properties create mode 100644 src/main/resources/log4j.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5c259d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* \ No newline at end of file diff --git a/link-serv.iml b/link-serv.iml new file mode 100644 index 0000000..64c6c51 --- /dev/null +++ b/link-serv.iml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/linkserv.iml b/linkserv.iml new file mode 100644 index 0000000..64c6c51 --- /dev/null +++ b/linkserv.iml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..14c421c --- /dev/null +++ b/pom.xml @@ -0,0 +1,98 @@ + + + 4.0.0 + + link-serv + link-serv + 1.0-SNAPSHOT + war + + + org.springframework.boot + spring-boot-starter-parent + LATEST + + + + 14 + org.bibalex.linkserv.MainLinkServ + + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework + spring-web + LATEST + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + + + + org.springframework.boot + spring-boot-starter-data-rest + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-actuator + + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + + org.neo4j + neo4j + LATEST + + + + org.neo4j.driver + neo4j-java-driver + LATEST + + + + org.json + json + 20180130 + + + + org.apache.logging.log4j + log4j-core + 2.7 + + + + org.apache.logging.log4j + log4j-api + 2.7 + + + \ No newline at end of file diff --git a/src/main/java/org/bibalex/linkserv/MainLinkServ.java b/src/main/java/org/bibalex/linkserv/MainLinkServ.java new file mode 100644 index 0000000..dc503cf --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/MainLinkServ.java @@ -0,0 +1,27 @@ +package org.bibalex.linkserv; + +import org.bibalex.linkserv.handlers.PropertiesHandler; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +import java.io.IOException; + +@SpringBootApplication +public class MainLinkServ extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(MainLinkServ.class); + } + + public static void main (String [] args){ + try { + PropertiesHandler.initializeProperties(); + } catch (IOException e) { + e.printStackTrace(); + } + SpringApplication.run(MainLinkServ.class, args); + } +} diff --git a/src/main/java/org/bibalex/linkserv/controllers/LinkServController.java b/src/main/java/org/bibalex/linkserv/controllers/LinkServController.java new file mode 100644 index 0000000..8965c67 --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/controllers/LinkServController.java @@ -0,0 +1,52 @@ +package org.bibalex.linkserv.controllers; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.bibalex.linkserv.errors.OperationNotFoundException; +import org.bibalex.linkserv.handlers.PropertiesHandler; +import org.bibalex.linkserv.services.LinkServService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/") +public class LinkServController { + + @Autowired + private LinkServService linkServService; + + private static final Logger LOGGER = LogManager.getLogger(LinkServController.class); + + @RequestMapping(value = "/{workspaceName}", method = RequestMethod.POST) + public ResponseEntity updateGraph(@PathVariable("workspaceName") String workspaceName, + @RequestBody String jsonGraph, + @RequestParam String operation) { + + LOGGER.info("Updating Graph with Parameters: " + workspaceName); + if (operation.equals(PropertiesHandler.getProperty("updateGraph"))) { + LOGGER.info("Response Status: 200"); + return ResponseEntity.ok(linkServService.updateGraph(jsonGraph)); + } else { + LOGGER.error("Response Status: 500, Operation Not Found: " + operation); + throw new OperationNotFoundException(operation); + } + } + + @RequestMapping(method = RequestMethod.GET, value = "/{workspaceName}") + public ResponseEntity getGraph(@PathVariable("workspaceName") String workspaceName, + @RequestParam String operation, + @RequestParam(required = false, defaultValue = "1") Integer depth) { + + LOGGER.info("Getting Graph with Parameters: " + workspaceName + " and Depth: " + depth); + if (operation.equals(PropertiesHandler.getProperty("getGraph"))) { + LOGGER.info("Response Status: 200"); + return ResponseEntity.ok(linkServService.getGraph(workspaceName, depth)); + } else { + LOGGER.error("Response Status: 500, Operation Not Found: " + operation); + throw new OperationNotFoundException(operation); + } + + } + +} \ No newline at end of file diff --git a/src/main/java/org/bibalex/linkserv/errors/OperationNotFoundException.java b/src/main/java/org/bibalex/linkserv/errors/OperationNotFoundException.java new file mode 100644 index 0000000..ae9bc68 --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/errors/OperationNotFoundException.java @@ -0,0 +1,9 @@ +package org.bibalex.linkserv.errors; + +public class OperationNotFoundException extends RuntimeException { + + public OperationNotFoundException(String operation) { + super("Invalid operation: " + operation); + } + +} \ No newline at end of file diff --git a/src/main/java/org/bibalex/linkserv/handlers/JSONHandler.java b/src/main/java/org/bibalex/linkserv/handlers/JSONHandler.java new file mode 100644 index 0000000..ed4c2b0 --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/handlers/JSONHandler.java @@ -0,0 +1,174 @@ +package org.bibalex.linkserv.handlers; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bibalex.linkserv.models.Edge; +import org.bibalex.linkserv.models.Node; +import org.json.JSONObject; + +import java.util.ArrayList; + +public class JSONHandler { + + private Neo4jHandler neo4jHandler; + private ArrayList graphData; + private ArrayList getGraphResults; + + private static final int DEFAULT_ATTRIBUTE_VALUE = 1; + private static final Logger LOGGER = LogManager.getLogger(JSONHandler.class); + + public JSONHandler(){ + this.neo4jHandler = new Neo4jHandler(); + this.graphData = new ArrayList<>(); + } + + public ArrayList getProperties(String jsonLine){ + + JSONObject jsonData = new JSONObject(jsonLine); + if(!jsonData.isNull(PropertiesHandler.getProperty("addNodeKey"))){ + LOGGER.info("Adding Node through Line: " + jsonLine); + handleNode(jsonData); + } + else{ + LOGGER.info("Adding Edge through Line: " + jsonLine); + handleEdge(jsonData); + } + return graphData; + } + + private void handleNode(JSONObject jsonData){ + + JSONObject jsonNode = jsonData.getJSONObject(PropertiesHandler.getProperty("addNodeKey")); + String nodeId = jsonNode.keys().next(); + JSONObject JsonNodeProperties = jsonNode.getJSONObject(nodeId); + if(JsonNodeProperties.isNull(PropertiesHandler.getProperty("versionKey"))) { + Node node = new Node(nodeId,PropertiesHandler.getProperty("parentNodeLabel"), + JsonNodeProperties.getString(PropertiesHandler.getProperty("labelKey")), null); + graphData.add(node); + LOGGER.info("Parent Node Added: " + nodeId); + } + else{ + Node node = new Node(nodeId, PropertiesHandler.getProperty("versionNodeLabel"), + JsonNodeProperties.getString(PropertiesHandler.getProperty("labelKey")), + JsonNodeProperties.getString(PropertiesHandler.getProperty("versionKey"))); + graphData.add(node); + LOGGER.info("Version Node Added: " + nodeId); + } + } + + private void handleEdge(JSONObject jsonData){ + + JSONObject jsonEdge = jsonData.getJSONObject(PropertiesHandler.getProperty("addEdgeKey")); + String edgeId = jsonEdge.keys().next(); + JSONObject JsonEdgeProperties = jsonEdge.getJSONObject(edgeId); + Edge edge = new Edge(edgeId, PropertiesHandler.getProperty("linkRelationshipType"), + JsonEdgeProperties.getString(PropertiesHandler.getProperty("sourceKey")), + JsonEdgeProperties.getString(PropertiesHandler.getProperty("targetKey"))); + graphData.add(edge); + } + + public ArrayList getGraph(String url, String timestamp, Integer depth) { + + getGraphResults = new ArrayList<>(); + ArrayList nodesNames = new ArrayList<>(); + Node rootNode = neo4jHandler.getRootNode(url, timestamp); + + if (!validatePresenceOfAttributes(rootNode, depth)) { + getGraphResults.add(new JSONObject()); + LOGGER.info("No Results Found or Invalid Depth"); + return getGraphResults; + } + + /** get the actual timestamp of the returned root node in case of approximation later on, + where the given timestamp of the request is not necessarily equal to the actual one returned.**/ + String nodeVersion = rootNode.getTimestamp(); + nodesNames.add(rootNode.getUrl()); + getGraphResults.add(addNodeToResults(rootNode)); + + for(int i = 0; i < depth; i++){ + nodesNames = getOutlinkNodes(nodesNames,nodeVersion); + } + return getGraphResults; + } + + private boolean validatePresenceOfAttributes(Node rootNode, int depth){ + if (rootNode.equals(null) || depth < 1){ + return false; + } + return true; + } + + private ArrayList getOutlinkNodes(ArrayList nodesNames, String nodeVersion){ + + ArrayList outlinkNodes = new ArrayList<>(); + for(String nodeName : nodesNames) { + ArrayList outlinkData = neo4jHandler.getOutlinkNodes(nodeName, nodeVersion); + for (Object nodeMap : outlinkData) { + if (nodeMap.getClass() == Node.class) { + getGraphResults.add(addNodeToResults((Node) nodeMap)); + outlinkNodes.add(((Node) nodeMap).getUrl()); + } else + getGraphResults.add(addEdgeToResults((Edge) nodeMap)); + } + } + return outlinkNodes; + } + + private JSONObject addNodeToResults(Node node) { + + JSONObject outlinkNodeData = new JSONObject(); + outlinkNodeData.put(PropertiesHandler.getProperty("nameKey"), node.getUrl()); + outlinkNodeData.put(PropertiesHandler.getProperty("versionKey"), node.getTimestamp()); + outlinkNodeData.put(PropertiesHandler.getProperty("typeKey"), node.getType()); + outlinkNodeData = setDefaultNodeAttributes(outlinkNodeData); + + JSONObject fullNode = new JSONObject(); + String nodeID = node.getId(); + fullNode.put(nodeID, outlinkNodeData); + + JSONObject nodeJSON = new JSONObject(); + nodeJSON.put(PropertiesHandler.getProperty("addNodeKey"), fullNode); + + return nodeJSON; + } + + private JSONObject addEdgeToResults(Edge edge) { + + JSONObject outlinkEdgeData = new JSONObject(); + + outlinkEdgeData.put(PropertiesHandler.getProperty("sourceKey"), edge.getSource()); + outlinkEdgeData.put(PropertiesHandler.getProperty("targetKey"), edge.getTarget()); + outlinkEdgeData.put(PropertiesHandler.getProperty("typeKey"), edge.getType()); + outlinkEdgeData.put("directed", true); + outlinkEdgeData.put("r", DEFAULT_ATTRIBUTE_VALUE); + outlinkEdgeData.put("g", DEFAULT_ATTRIBUTE_VALUE); + outlinkEdgeData.put("b", DEFAULT_ATTRIBUTE_VALUE); + outlinkEdgeData.put("weight", DEFAULT_ATTRIBUTE_VALUE); + + JSONObject fullEdge = new JSONObject(); + fullEdge.put(edge.getId(), outlinkEdgeData); + + JSONObject edgeJSON = new JSONObject(); + edgeJSON.put(PropertiesHandler.getProperty("addEdgeKey"), fullEdge); + + return edgeJSON; + } + + private JSONObject setDefaultNodeAttributes(JSONObject nodeData) { + + String[] attributes = PropertiesHandler.getProperty("nodeAttributes").split(","); + + for(String attribute : attributes) { + nodeData.put(attribute, DEFAULT_ATTRIBUTE_VALUE); + } + return nodeData; + } + + public ArrayList getGraphData() { + return graphData; + } + + public void setGraphData(ArrayList graphData) { + this.graphData = graphData; + } +} diff --git a/src/main/java/org/bibalex/linkserv/handlers/Neo4jHandler.java b/src/main/java/org/bibalex/linkserv/handlers/Neo4jHandler.java new file mode 100644 index 0000000..8c911c6 --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/handlers/Neo4jHandler.java @@ -0,0 +1,136 @@ +package org.bibalex.linkserv.handlers; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bibalex.linkserv.models.Edge; +import org.bibalex.linkserv.models.Node; +import org.neo4j.driver.*; +import org.neo4j.driver.Record; + +import java.util.ArrayList; + +import static org.neo4j.driver.Values.parameters; + +public class Neo4jHandler { + + private String versionNodeLabel; + private String parentNodeLabel; + private String linkRelationshipType; + private Session session; + + private static final Logger LOGGER = LogManager.getLogger(Neo4jHandler.class); + + public void Neo4jHandler(){ + this.versionNodeLabel = PropertiesHandler.getProperty("versionNodeLabel"); + this.parentNodeLabel = PropertiesHandler.getProperty("parentNodeLabel"); + this.linkRelationshipType = PropertiesHandler.getProperty("linkRelationshipType"); + } + + public Session getSession() { + if (session == null || !session.isOpen()) { + Driver driver = GraphDatabase.driver( PropertiesHandler.getProperty("uri")); + session = driver.session(); + } + return session; + } + + // v.version is returned by the query in case of approximation later on + public Node getRootNode(String url, String timestamp) { + + LOGGER.info("Getting Root Node of URL: " + url + " with Timestamp: " + timestamp); + + Node rootNode = null; + Value parameterValues = parameters("version", timestamp, "url", url); + + String query = "CALL linkserv." + PropertiesHandler.getProperty("getRootNodeProcedure") + "($url, $version);"; + + Result result = getSession().run(query, parameterValues); + + while (result.hasNext()) { + Record rootNodeRecord = result.next(); + rootNode = new Node(convertValueToString(rootNodeRecord.get("nodeId")), + versionNodeLabel, + convertValueToString(rootNodeRecord.get("parentName")), + convertValueToString(rootNodeRecord.get("versionName"))); + } + return rootNode; + } + + // get the closest version to the rootNodeVersion, we'll just assume they're the same for now + public ArrayList getOutlinkNodes(String nodeName, String nodeVersion) { + + LOGGER.info("Getting Outlinks of Node of URL: " + nodeName + " with Timestamp: " + nodeVersion); + + ArrayList outlinkEntities = new ArrayList(); + Value parameterValues = parameters("name", nodeName, "version", nodeVersion); + + String query = "CALL linkserv." + PropertiesHandler.getProperty("getOutlinkNodesProcedure") + "($name, $version);"; + + Result result = getSession().run(query, parameterValues); + + while (result.hasNext()) { + + Record resultRecord = result.next(); + Boolean isParent = convertValueToString(resultRecord.get("outlinkVersion")).equalsIgnoreCase("NULL"); + + Node outlinkNode = new Node(isParent ? convertValueToString(resultRecord.get("parentId")) : + convertValueToString(resultRecord.get("outlinkVersionId")), + isParent ? parentNodeLabel : versionNodeLabel, + convertValueToString(resultRecord.get("outlinkName")), + isParent ? "" : convertValueToString(resultRecord.get("outlinkVersion"))); + + Edge outlinkEdge = new Edge(convertValueToString(resultRecord.get("relationshipId")), + linkRelationshipType, + convertValueToString(resultRecord.get("parentVersionId")), + isParent ? convertValueToString(resultRecord.get("parentId")) : + convertValueToString(resultRecord.get("outlinkVersionId"))); + + outlinkEntities.add(outlinkNode); + outlinkEntities.add(outlinkEdge); + } + return outlinkEntities; + } + + private String convertValueToString(Value value) { + return String.valueOf(value).replace("\"", ""); + } + + public boolean addNodesAndRelationships(ArrayList data) { + + LOGGER.info("Update Graph: Adding Nodes and Edges"); + LOGGER.debug(data); + + ArrayList outlinks = new ArrayList<>(); + String url=""; + String timestamp=""; + String query; + + for (int i = 0; i < data.size(); i++) { + if (data.get(i).getClass() == Node.class) { + Node node = (Node) data.get(i); + + if (node.getTimestamp() == null) { + outlinks.add(node.getUrl()); + } else { + url = node.getUrl(); + timestamp = node.getTimestamp(); + } + } else { + // Here we will handle multiple timestamps request + } + } + Value parameters = parameters("url", url, "timestamp", timestamp, "outlinks", outlinks); + query = "CALL linkserv." + PropertiesHandler.getProperty("addNodesAndRelationshipsProcedure") + +"($url,$timestamp,$outlinks)"; + + Result result = getSession().run(query, parameters); + + if (result.hasNext()) { + LOGGER.info("Graph Updated Successfully"); + return true; + } else { + LOGGER.info("Could not Update Graph"); + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/bibalex/linkserv/handlers/PropertiesHandler.java b/src/main/java/org/bibalex/linkserv/handlers/PropertiesHandler.java new file mode 100644 index 0000000..1528cb1 --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/handlers/PropertiesHandler.java @@ -0,0 +1,18 @@ +package org.bibalex.linkserv.handlers; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class PropertiesHandler { + static Properties prop = new Properties(); + + public static void initializeProperties() throws IOException { + InputStream input = PropertiesHandler.class.getClassLoader().getResourceAsStream("config.properties"); + prop.load(input); + } + + public static String getProperty(String key){ + return prop.getProperty(key); + } +} diff --git a/src/main/java/org/bibalex/linkserv/handlers/WorkspaceNameHandler.java b/src/main/java/org/bibalex/linkserv/handlers/WorkspaceNameHandler.java new file mode 100644 index 0000000..f74d90b --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/handlers/WorkspaceNameHandler.java @@ -0,0 +1,27 @@ +package org.bibalex.linkserv.handlers; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.HashMap; +import java.util.Map; + +public class WorkspaceNameHandler { + + private static final Logger LOGGER = LogManager.getLogger(WorkspaceNameHandler.class); + + public Map splitWorkspaceName(String workspaceName){ + + LOGGER.info("Splitting: \"" + workspaceName + "\""); + Map workspaceParameters = new HashMap(); + String [] parameters = workspaceName.split(","); + + workspaceParameters.put(PropertiesHandler.getProperty("workspaceTimestamp"), parameters[0]); + workspaceParameters.put(PropertiesHandler.getProperty("workspaceURL"), parameters[1]); + + LOGGER.info("URL: " + workspaceParameters.get("url")); + LOGGER.info("Timestamp: " + workspaceParameters.get("timestamp")); + + return workspaceParameters; + } +} diff --git a/src/main/java/org/bibalex/linkserv/models/Edge.java b/src/main/java/org/bibalex/linkserv/models/Edge.java new file mode 100644 index 0000000..6ea280a --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/models/Edge.java @@ -0,0 +1,48 @@ +package org.bibalex.linkserv.models; + +public class Edge { + + private String id; + private String type; + private String source; + private String target; + + public Edge(String id, String type, String source, String target) { + this.id = id; + this.type = type; + this.source = source; + this.target = target; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/src/main/java/org/bibalex/linkserv/models/Node.java b/src/main/java/org/bibalex/linkserv/models/Node.java new file mode 100644 index 0000000..a93ec88 --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/models/Node.java @@ -0,0 +1,47 @@ +package org.bibalex.linkserv.models; + +public class Node { + private String id; + private String type; + private String url; + private String timestamp; + + public Node(String id, String type, String url, String timestamp) { + this.id = id; + this.type = type; + this.url = url; + this.timestamp = timestamp; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } +} diff --git a/src/main/java/org/bibalex/linkserv/services/LinkServService.java b/src/main/java/org/bibalex/linkserv/services/LinkServService.java new file mode 100644 index 0000000..b7fb69c --- /dev/null +++ b/src/main/java/org/bibalex/linkserv/services/LinkServService.java @@ -0,0 +1,81 @@ +package org.bibalex.linkserv.services; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bibalex.linkserv.handlers.JSONHandler; +import org.bibalex.linkserv.handlers.Neo4jHandler; +import org.bibalex.linkserv.handlers.PropertiesHandler; +import org.bibalex.linkserv.handlers.WorkspaceNameHandler; +import org.json.JSONObject; +import org.springframework.stereotype.Service; + +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Map; + +@Service + +public class LinkServService { + + private WorkspaceNameHandler workspaceNameHandler = new WorkspaceNameHandler(); + private Neo4jHandler neo4jHandler = new Neo4jHandler(); + private JSONHandler jsonHandler; + + private static final Logger LOGGER = LogManager.getLogger(LinkServService.class); + + public String getGraph(String workspaceName, Integer depth) { + + jsonHandler = new JSONHandler(); + + Map workspaceNameParameters = workspaceNameHandler.splitWorkspaceName(workspaceName); + + String url = workspaceNameParameters.get(PropertiesHandler.getProperty("workspaceURL")); + String timestamp = workspaceNameParameters.get(PropertiesHandler.getProperty("workspaceTimestamp")); + String jsonResponse = ""; + + LOGGER.info("Get Graph of: " + url + " with Version: " + timestamp + " and Depth: " + depth); + + ArrayList graphJsonArray = jsonHandler.getGraph(url, timestamp, depth); + + for(JSONObject json : graphJsonArray) { + jsonResponse += (json.toString()) + "\n"; + } + + if (jsonResponse.isEmpty()) { + LOGGER.info("No Match Found"); + } else { + LOGGER.debug("Graph Returned: " + jsonResponse); + LOGGER.info("Returned Match Successfully"); + } + return jsonResponse; + } + + public String updateGraph(String jsonGraph) { + + LOGGER.info("Update Graph"); + + jsonHandler = new JSONHandler(); + jsonGraph = URLDecoder.decode(jsonGraph); + if (jsonGraph.contains("&")) { + jsonGraph = jsonGraph.split("&")[1]; + } + // Gephi uses \\r as splitter between json lines + String[] jsonLines = jsonGraph.split("\\r"); + for (String jsonLine : jsonLines) { + jsonHandler.getProperties(jsonLine); + + } + boolean done = neo4jHandler.addNodesAndRelationships(jsonHandler.getGraphData()); + if (done) { + jsonGraph = jsonGraph.replace("=", ""); + jsonGraph = jsonGraph.replace("\\r", ""); + + LOGGER.info("Graph Updated Successfully"); + LOGGER.debug("JSON Data: " + jsonGraph); + return jsonGraph + "\n"; + } else + LOGGER.info("Could not Update Graph"); + LOGGER.debug("JSON Data: " + jsonGraph); + return ""; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..a5b86c4 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,11 @@ +server.port = 8020 + +#logging.level.org.bibalex.links-serv.neo4j= DEBUG +#logging.level.org.springframework.web= DEBUG + +#resourcesDirectory= +neo4jDirectory = /home/ba/neo4j-community-3.2.14/ + +# Server compression +server.compression.enabled=true +server.compression.mime-types=application/json \ No newline at end of file diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties new file mode 100644 index 0000000..b201540 --- /dev/null +++ b/src/main/resources/config.properties @@ -0,0 +1,29 @@ +#JSON properties +addNodeKey = an +addEdgeKey = ae +versionKey = timestamp +labelKey = label +nameKey = url +sourceKey = source +targetKey = target +typeKey = TYPE +nodeAttributes = r,g,b,x,y,z,size + +#Neo4j properties +versionNodeLabel = VersionNode +parentNodeLabel = ParentNode +linkRelationshipType = LINKED_TO +getRootNodeProcedure = getRootNode +getOutlinkNodesProcedure = getOutlinkNodes +addNodesAndRelationshipsProcedure = addNodesAndRelationships + +#Neo4j Driver +uri = bolt://localhost:7687 + +#workspace name +workspaceURL = url +workspaceTimestamp = timestamp + +#operations +updateGraph = updateGraph +getGraph = getGraph \ No newline at end of file diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties new file mode 100644 index 0000000..1def169 --- /dev/null +++ b/src/main/resources/log4j.properties @@ -0,0 +1,14 @@ +log4j.rootLogger = INFO, file, console + +#redirect log messages to log file, support file logging +log4j.appender.file = org.apache.log4j.RollingFileAppender +log4j.appender.file.File = /home/ba/IdeaProjects/linkserv/logs/app.log +log4j.appender.file.MaxFileSize = 100MB +log4j.appender.file.MaxBackupIndex = 10 + +log4j.appender.file.layout = org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern = %d{yyyy-MMM-dd HH:mm:ss} %-5p %C{36}.%M:%L - %m%n + +log4j.appender.console = org.apache.log4j.ConsoleAppender +log4j.appender.console.layout = org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern = %d{yyyy-MMM-dd HH:mm:ss} %-5p %C{36}.%M:%L - %m%n \ No newline at end of file From ba64bae3c3985d3a412230c9e9a9243d99715e0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2020 18:37:27 +0000 Subject: [PATCH 2/2] Bump log4j-core from 2.7 to 2.13.2 Bumps log4j-core from 2.7 to 2.13.2. Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 14c421c..4108a7f 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ org.apache.logging.log4j log4j-core - 2.7 + 2.13.2