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 *******************************************************************************/
10 package it.polito.escape.verify.service;
13 import java.io.FileNotFoundException;
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
19 import java.util.Scanner;
21 import javax.ws.rs.InternalServerErrorException;
23 import com.fasterxml.jackson.databind.JsonNode;
24 import com.github.fge.jsonschema.core.exceptions.ProcessingException;
25 import com.github.fge.jsonschema.main.JsonSchema;
27 import it.polito.escape.verify.database.DatabaseClass;
28 import it.polito.escape.verify.exception.BadRequestException;
29 import it.polito.escape.verify.exception.DataNotFoundException;
30 import it.polito.escape.verify.exception.ForbiddenException;
31 import it.polito.escape.verify.model.Configuration;
32 import it.polito.escape.verify.model.Graph;
33 import it.polito.escape.verify.model.Neighbour;
34 import it.polito.escape.verify.model.Node;
36 public class NodeService {
38 private Map<Long, Graph> graphs = DatabaseClass.getInstance().getGraphs();
40 public NodeService() {
44 public List<Node> getAllNodes(long graphId) {
46 throw new ForbiddenException("Illegal graph id: " + graphId);
48 Graph graph = graphs.get(graphId);
50 throw new DataNotFoundException("Graph with id " + graphId + " not found");
51 Map<Long, Node> nodes = graph.getNodes();
52 return new ArrayList<Node>(nodes.values());
55 public Node getNode(long graphId, long nodeId) {
57 throw new ForbiddenException("Illegal graph id: " + graphId);
60 throw new ForbiddenException("Illegal node id: " + nodeId);
62 Graph graph = graphs.get(graphId);
64 throw new DataNotFoundException("Graph with id " + graphId + " not found");
65 Map<Long, Node> nodes = graph.getNodes();
66 Node node = nodes.get(nodeId);
68 throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId);
73 public Node updateNode(long graphId, Node node) {
75 throw new ForbiddenException("Illegal graph id: " + graphId);
77 if (node.getId() <= 0) {
78 throw new ForbiddenException("Illegal node id: " + node.getId());
80 Graph graph = graphs.get(graphId);
82 throw new DataNotFoundException("Graph with id " + graphId + " not found");
83 Map<Long, Node> nodes = graph.getNodes();
84 Node localNode = nodes.get(node.getId());
85 if (localNode == null) {
86 throw new DataNotFoundException("Node with id " + node.getId() + " not found in graph with id " + graphId);
89 Graph graphCopy = new Graph();
90 graphCopy.setId(graph.getId());
91 graphCopy.setNodes(new HashMap<Long, Node>(graph.getNodes()));
92 graphCopy.getNodes().remove(node.getId());
94 // int numberOfNeighbours = 0;
95 // for(Neighbour neighbour : node.getNeighbours().values()){
96 // neighbour.setId(++numberOfNeighbours);
99 for (Map.Entry<Long, Neighbour> neighbourEntry : node.getNeighbours().entrySet()) {
100 neighbourEntry.getValue().setId(neighbourEntry.getKey());
103 validateNode(graphCopy, node);
105 synchronized (this) {
106 nodes.put(node.getId(), node);
107 DatabaseClass.persistDatabase();
112 public Node removeNode(long graphId, long nodeId) {
114 throw new ForbiddenException("Illegal graph id: " + graphId);
117 throw new ForbiddenException("Illegal node id: " + nodeId);
119 Graph graph = graphs.get(graphId);
121 throw new DataNotFoundException("Graph with id " + graphId + " not found");
122 Map<Long, Node> nodes = graph.getNodes();
124 synchronized (this) {
125 return nodes.remove(nodeId);
129 public Node addNode(long graphId, Node node) {
131 throw new ForbiddenException("Illegal graph id: " + graphId);
133 Graph graph = graphs.get(graphId);
135 throw new DataNotFoundException("Graph with id " + graphId + " not found");
136 Map<Long, Node> nodes = graph.getNodes();
138 validateNode(graph, node);
140 synchronized (this) {
141 node.setId(DatabaseClass.getInstance().getGraphNumberOfNodes(graphId) + 1);
144 // int numberOfNeighbours = 0;
146 for (Map.Entry<Long, Neighbour> neighbourEntry : node.getNeighbours().entrySet()) {
147 neighbourEntry.getValue().setId(neighbourEntry.getKey());
150 // for (Neighbour neighbour : node.getNeighbours().values()) {
151 // neighbour.setId(++numberOfNeighbours);
154 synchronized (this) {
155 nodes.put(node.getId(), node);
156 DatabaseClass.persistDatabase();
161 public Node searchByName(long graphId, String nodeName) {
163 throw new ForbiddenException("Illegal graph id: " + graphId);
165 Graph graph = graphs.get(graphId);
167 throw new DataNotFoundException("Graph with id " + graphId + " not found");
168 Map<Long, Node> nodes = graph.getNodes();
170 for (Node node : nodes.values()) {
171 if (node.getName().equals(nodeName))
177 public static void validateNode(Graph graph, Node node) {
179 throw new BadRequestException("Node validation failed: cannot validate null graph");
181 throw new BadRequestException("Node validation failed: cannot validate null node");
183 if (node.getName() == null)
184 throw new BadRequestException("Node validation failed: node 'name' field cannot be null");
185 if (node.getFunctional_type() == null)
186 throw new BadRequestException("Node validation failed: node 'functional_type' field cannot be null");
188 if (node.getName().equals(""))
189 throw new BadRequestException("Node validation failed: node 'name' field cannot be an empty string");
190 if (node.getFunctional_type().equals(""))
191 throw new BadRequestException("Node validation failed: node 'functional_type' field cannot be an empty string");
193 Node nodeFound = graph.searchNodeByName(node.getName());
194 if ((nodeFound != null) && (nodeFound.equals(node) == false))
195 throw new BadRequestException("Node validation failed: graph already has a node named '" + node.getName()
197 Configuration configuration = node.getConfiguration();
198 if (configuration != null) {
199 JsonNode configurationJsonNode = configuration.getConfiguration();
200 // validate configuration against schema file
201 validateNodeConfigurationAgainstSchemaFile(node, configurationJsonNode);
202 JsonValidationService jsonValidator = new JsonValidationService(graph, node);
203 boolean hasCustomValidator = jsonValidator.validateNodeConfiguration();
204 if (!hasCustomValidator) {
205 jsonValidator.validateFieldsAgainstNodeNames(configurationJsonNode);
209 // validate neighbours
210 Map<Long, Neighbour> nodeNeighboursMap = node.getNeighbours();
211 if (nodeNeighboursMap == null)
212 throw new BadRequestException("Node validation failed: node 'neighbours' cannot be null");
213 for (Neighbour neighbour : nodeNeighboursMap.values()) {
214 NeighbourService.validateNeighbour(graph, node, neighbour);
218 public static void validateNodeConfigurationAgainstSchemaFile(Node node, JsonNode configurationJson) {
219 String schemaFileName = node.getFunctional_type() + ".json";
221 File schemaFile = new File(System.getProperty("catalina.base") + "/webapps/verify/json/" + schemaFileName);
223 if (!schemaFile.exists()) {
224 //if no REST client, try gRPC application
225 schemaFile = new File("src/main/webapp/json/" + schemaFileName);
227 if (!schemaFile.exists()) {
228 throw new ForbiddenException("Functional type '" + node.getFunctional_type()
229 + "' is not supported! Please edit 'functional_type' field of node '"
230 + node.getName() + "'");
234 JsonSchema schemaNode = null;
236 schemaNode = ValidationUtils.getSchemaNode(schemaFile);
238 catch (IOException e) {
239 throw new InternalServerErrorException("Unable to load '" + schemaFileName + "' schema file");
241 catch (ProcessingException e) {
242 throw new InternalServerErrorException("Unable to resolve '" + schemaFileName
243 + "' schema file as a schema node");
247 ValidationUtils.validateJson(schemaNode, configurationJson);
249 catch (ProcessingException e) {
250 throw new BadRequestException("Something went wrong trying to validate node '" + node.getName()
251 + "' with the following configuration: '" + configurationJson.toString()
252 + "' against the json schema '" + schemaFile.getName() + "': "