1 /*******************************************************************************
2 * Copyright (c) 2017 Politecnico di Torino and others.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Apache License, Version 2.0
6 * which accompanies this distribution, and is available at
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *******************************************************************************/
9 package it.polito.verigraph.service;
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
17 import javax.ws.rs.InternalServerErrorException;
18 import javax.xml.bind.JAXBException;
19 import com.fasterxml.jackson.core.JsonParseException;
20 import com.fasterxml.jackson.core.JsonProcessingException;
21 import com.fasterxml.jackson.databind.JsonMappingException;
22 import com.fasterxml.jackson.databind.JsonNode;
23 import com.github.fge.jsonschema.core.exceptions.ProcessingException;
24 import com.github.fge.jsonschema.main.JsonSchema;
25 import it.polito.neo4j.exceptions.MyInvalidIdException;
26 import it.polito.neo4j.exceptions.MyNotFoundException;
27 import it.polito.neo4j.manager.Neo4jDBManager;
28 import it.polito.verigraph.exception.BadRequestException;
29 import it.polito.verigraph.exception.DataNotFoundException;
30 import it.polito.verigraph.exception.ForbiddenException;
31 import it.polito.verigraph.model.Configuration;
32 import it.polito.verigraph.model.Graph;
33 import it.polito.verigraph.model.Neighbour;
34 import it.polito.verigraph.model.Node;
36 public class NodeService {
38 private Neo4jDBManager manager=new Neo4jDBManager();
40 public NodeService() {}
42 public List<Node> getAllNodes(long graphId) throws JsonParseException, JsonMappingException, JAXBException, IOException, MyNotFoundException {
44 throw new ForbiddenException("Illegal graph id: " + graphId);
47 /*il controllo sull'esistenza del grafo viene fatto all'interno della getNodes
51 Map<Long, Node> nodes =manager.getNodes(graphId);
52 return new ArrayList<Node>(nodes.values());
55 public Node getNode(long graphId, long nodeId) throws JsonParseException, JsonMappingException, JAXBException, IOException, MyNotFoundException {
57 throw new ForbiddenException("Illegal graph id: " + graphId);
60 throw new ForbiddenException("Illegal node id: " + nodeId);
63 Node node=manager.getNodeById(nodeId, graphId);
65 throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId);
70 public Node updateNode(long graphId, Node node) throws JAXBException, IOException, MyInvalidIdException {
72 throw new ForbiddenException("Illegal graph id: " + graphId);
74 if (node.getId() < 0) {
75 throw new ForbiddenException("Illegal node id: " + node.getId());
78 Graph graph=manager.getGraph(graphId);
79 validateNode(graph, node);
81 Node n=manager.updateNode(graphId, node, node.getId());
82 validateNode(graph, n);
87 public Node removeNode(long graphId, long nodeId) throws JsonParseException, JsonMappingException, JAXBException, IOException {
89 throw new ForbiddenException("Illegal graph id: " + graphId);
92 throw new ForbiddenException("Illegal node id: " + nodeId);
95 Graph graph=manager.getGraph(graphId);
97 throw new DataNotFoundException("Graph with id " + graphId + " not found");
98 Node n=manager.deleteNode(graphId, nodeId);
102 public Node addNode(long graphId, Node node) throws JsonParseException, JsonMappingException, JAXBException, IOException, MyInvalidIdException {
104 throw new ForbiddenException("Illegal graph id: " + graphId);
107 Graph graph=manager.getGraph(graphId);
108 validateNode(graph, node);
109 Node n=manager.addNode(graphId, node);
110 validateNode(graph, n);
114 public Node searchByName(long graphId, String nodeName) throws JsonParseException, JsonMappingException, JAXBException, IOException {
116 throw new ForbiddenException("Illegal graph id: " + graphId);
118 Graph graph = manager.getGraph(graphId);
120 throw new DataNotFoundException("Graph with id " + graphId + " not found");
121 Map<Long, Node> nodes = graph.getNodes();
122 for (Node node : nodes.values()) {
123 if (node.getName().equals(nodeName))
129 public static void validateNode(Graph graph, Node node) throws JsonProcessingException {
131 throw new BadRequestException("Node validation failed: cannot validate null graph");
133 throw new BadRequestException("Node validation failed: cannot validate null node");
135 if (node.getName() == null)
136 throw new BadRequestException("Node validation failed: node 'name' field cannot be null");
137 if (node.getFunctional_type() == null)
138 throw new BadRequestException("Node validation failed: node 'functional_type' field cannot be null");
140 if (node.getName().equals(""))
141 throw new BadRequestException("Node validation failed: node 'name' field cannot be an empty string");
142 if (node.getFunctional_type().equals(""))
143 throw new BadRequestException("Node validation failed: node 'functional_type' field cannot be an empty string");
145 Node nodeFound =graph.searchNodeByName(node.getName());
146 if ((nodeFound != null) && (nodeFound.equals(node) == false))
147 throw new BadRequestException("Node validation failed: graph already has a node named '"+ node.getName()
149 Configuration configuration = node.getConfiguration();
150 if (configuration != null) {
151 JsonNode configurationJsonNode = configuration.getConfiguration();
152 // validate configuration against schema file
153 validateNodeConfigurationAgainstSchemaFile(node, configurationJsonNode);
154 JsonValidationService jsonValidator = new JsonValidationService(graph, node);
155 boolean hasCustomValidator = jsonValidator.validateNodeConfiguration();
156 if (!hasCustomValidator) {
157 jsonValidator.validateFieldsAgainstNodeNames(configurationJsonNode);
161 // validate neighbours
162 Map<Long, Neighbour> nodeNeighboursMap = node.getNeighbours();
163 if (nodeNeighboursMap == null)
164 throw new BadRequestException("Node validation failed: node 'neighbours' cannot be null");
165 for (Neighbour neighbour : nodeNeighboursMap.values()) {
166 NeighbourService.validateNeighbour(graph, node, neighbour);
170 public static void validateNodeConfigurationAgainstSchemaFile(Node node, JsonNode configurationJson) {
171 String schemaFileName = node.getFunctional_type() + ".json";
173 File schemaFile = new File(System.getProperty("catalina.base") + "/webapps/verigraph/jsonschema/" + schemaFileName);
175 if (!schemaFile.exists()) {
176 //if no REST client, try gRPC application
177 schemaFile = new File(System.getProperty("user.dir") + "/jsonschema/" + schemaFileName);
179 if (!schemaFile.exists()) {
180 throw new ForbiddenException("Functional type '"+ node.getFunctional_type()
181 + "' is not supported! Please edit 'functional_type' field of node '"
182 + node.getName() + "'");
186 JsonSchema schemaNode = null;
188 schemaNode = ValidationUtils.getSchemaNode(schemaFile);
190 catch (IOException e) {
191 throw new InternalServerErrorException("Unable to load '" + schemaFileName + "' schema file");
193 catch (ProcessingException e) {
194 throw new InternalServerErrorException("Unable to resolve '"+ schemaFileName
195 + "' schema file as a schema node");
199 ValidationUtils.validateJson(schemaNode, configurationJson);
201 catch (ProcessingException e) {
202 throw new BadRequestException("Something went wrong trying to validate node '"+ node.getName()
203 + "' with the following configuration: '" + configurationJson.toString()
204 + "' against the json schema '" + schemaFile.getName() + "': "
210 public Configuration addNodeConfiguration(long graphId, long nodeId, Configuration nodeConfiguration) throws IOException, MyInvalidIdException {
212 throw new ForbiddenException("Illegal graph id: " + graphId);
215 throw new ForbiddenException("Illegal node id: " + nodeId);
218 Node node=manager.getNodeById(nodeId, graphId);
219 validateNodeConfigurationAgainstSchemaFile(node, nodeConfiguration.getConfiguration());
220 Configuration newConf=manager.updateConfiguration(nodeId, graphId, nodeConfiguration, node);