Stop installing librairies during tests
[parser.git] / verigraph / src / main / java / it / polito / escape / verify / service / NodeService.java
1 /*******************************************************************************
2  * Copyright (c) 2017 Politecnico di Torino and others.
3  *
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
10 package it.polito.escape.verify.service;
11
12 import java.io.File;
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;
18 import java.util.Map;
19 import java.util.Scanner;
20
21 import javax.ws.rs.InternalServerErrorException;
22
23 import com.fasterxml.jackson.databind.JsonNode;
24 import com.github.fge.jsonschema.core.exceptions.ProcessingException;
25 import com.github.fge.jsonschema.main.JsonSchema;
26
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;
35
36 public class NodeService {
37
38         private Map<Long, Graph> graphs = DatabaseClass.getInstance().getGraphs();
39
40         public NodeService() {
41
42         }
43
44         public List<Node> getAllNodes(long graphId) {
45                 if (graphId <= 0) {
46                         throw new ForbiddenException("Illegal graph id: " + graphId);
47                 }
48                 Graph graph = graphs.get(graphId);
49                 if (graph == null)
50                         throw new DataNotFoundException("Graph with id " + graphId + " not found");
51                 Map<Long, Node> nodes = graph.getNodes();
52                 return new ArrayList<Node>(nodes.values());
53         }
54
55         public Node getNode(long graphId, long nodeId) {
56                 if (graphId <= 0) {
57                         throw new ForbiddenException("Illegal graph id: " + graphId);
58                 }
59                 if (nodeId <= 0) {
60                         throw new ForbiddenException("Illegal node id: " + nodeId);
61                 }
62                 Graph graph = graphs.get(graphId);
63                 if (graph == null)
64                         throw new DataNotFoundException("Graph with id " + graphId + " not found");
65                 Map<Long, Node> nodes = graph.getNodes();
66                 Node node = nodes.get(nodeId);
67                 if (node == null) {
68                         throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId);
69                 }
70                 return node;
71         }
72
73         public Node updateNode(long graphId, Node node) {
74                 if (graphId <= 0) {
75                         throw new ForbiddenException("Illegal graph id: " + graphId);
76                 }
77                 if (node.getId() <= 0) {
78                         throw new ForbiddenException("Illegal node id: " + node.getId());
79                 }
80                 Graph graph = graphs.get(graphId);
81                 if (graph == null)
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);
87                 }
88
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());
93
94                 // int numberOfNeighbours = 0;
95                 // for(Neighbour neighbour : node.getNeighbours().values()){
96                 // neighbour.setId(++numberOfNeighbours);
97                 // }
98
99                 for (Map.Entry<Long, Neighbour> neighbourEntry : node.getNeighbours().entrySet()) {
100                         neighbourEntry.getValue().setId(neighbourEntry.getKey());
101                 }
102
103                 validateNode(graphCopy, node);
104
105                 synchronized (this) {
106                         nodes.put(node.getId(), node);
107                         DatabaseClass.persistDatabase();
108                         return node;
109                 }
110         }
111
112         public Node removeNode(long graphId, long nodeId) {
113                 if (graphId <= 0) {
114                         throw new ForbiddenException("Illegal graph id: " + graphId);
115                 }
116                 if (nodeId <= 0) {
117                         throw new ForbiddenException("Illegal node id: " + nodeId);
118                 }
119                 Graph graph = graphs.get(graphId);
120                 if (graph == null)
121                         throw new DataNotFoundException("Graph with id " + graphId + " not found");
122                 Map<Long, Node> nodes = graph.getNodes();
123
124                 synchronized (this) {
125                         return nodes.remove(nodeId);
126                 }
127         }
128
129         public Node addNode(long graphId, Node node) {
130                 if (graphId <= 0) {
131                         throw new ForbiddenException("Illegal graph id: " + graphId);
132                 }
133                 Graph graph = graphs.get(graphId);
134                 if (graph == null)
135                         throw new DataNotFoundException("Graph with id " + graphId + " not found");
136                 Map<Long, Node> nodes = graph.getNodes();
137
138                 validateNode(graph, node);
139
140                 synchronized (this) {
141                         node.setId(DatabaseClass.getInstance().getGraphNumberOfNodes(graphId) + 1);
142                 }
143
144                 // int numberOfNeighbours = 0;
145
146                 for (Map.Entry<Long, Neighbour> neighbourEntry : node.getNeighbours().entrySet()) {
147                         neighbourEntry.getValue().setId(neighbourEntry.getKey());
148                 }
149
150                 // for (Neighbour neighbour : node.getNeighbours().values()) {
151                 // neighbour.setId(++numberOfNeighbours);
152                 // }
153
154                 synchronized (this) {
155                         nodes.put(node.getId(), node);
156                         DatabaseClass.persistDatabase();
157                         return node;
158                 }
159         }
160
161         public Node searchByName(long graphId, String nodeName) {
162                 if (graphId <= 0) {
163                         throw new ForbiddenException("Illegal graph id: " + graphId);
164                 }
165                 Graph graph = graphs.get(graphId);
166                 if (graph == null)
167                         throw new DataNotFoundException("Graph with id " + graphId + " not found");
168                 Map<Long, Node> nodes = graph.getNodes();
169
170                 for (Node node : nodes.values()) {
171                         if (node.getName().equals(nodeName))
172                                 return node;
173                 }
174                 return null;
175         }
176
177         public static void validateNode(Graph graph, Node node) {
178                 if (graph == null)
179                         throw new BadRequestException("Node validation failed: cannot validate null graph");
180                 if (node == null)
181                         throw new BadRequestException("Node validation failed: cannot validate null node");
182
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");
187
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");
192
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()
196                                                                                         + "'");
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);
206                         }
207                 }
208
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);
215                 }
216         }
217
218         public static void validateNodeConfigurationAgainstSchemaFile(Node node, JsonNode configurationJson) {
219                 String schemaFileName = node.getFunctional_type() + ".json";
220
221                 File schemaFile = new File(System.getProperty("catalina.base") + "/webapps/verify/json/" + schemaFileName);
222
223                 if (!schemaFile.exists()) {
224                         //if no REST client, try gRPC application
225                         schemaFile = new File("src/main/webapp/json/" + schemaFileName);
226
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() + "'");
231                         }
232                 }
233
234                 JsonSchema schemaNode = null;
235                 try {
236                         schemaNode = ValidationUtils.getSchemaNode(schemaFile);
237                 }
238                 catch (IOException e) {
239                         throw new InternalServerErrorException("Unable to load '" + schemaFileName + "' schema file");
240                 }
241                 catch (ProcessingException e) {
242                         throw new InternalServerErrorException("Unable to resolve '"    + schemaFileName
243                                                                                                         + "' schema file as a schema node");
244                 }
245
246                 try {
247                         ValidationUtils.validateJson(schemaNode, configurationJson);
248                 }
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() + "': "
253                                                                                         + e.getMessage());
254
255                 }
256
257         }
258 }