update verigraph
[parser.git] / verigraph / src / it / polito / verigraph / 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 package it.polito.verigraph.service;
10
11 import java.io.File;
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
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;
35
36 public class NodeService {
37
38     private Neo4jDBManager manager=new Neo4jDBManager();
39
40     public NodeService() {}
41
42     public List<Node> getAllNodes(long graphId) throws JsonParseException, JsonMappingException, JAXBException, IOException, MyNotFoundException {
43         if (graphId < 0) {
44             throw new ForbiddenException("Illegal graph id: " + graphId);
45         }
46
47         /*il controllo sull'esistenza del grafo viene fatto all'interno della getNodes
48
49          */
50
51         Map<Long, Node> nodes =manager.getNodes(graphId);
52         return new ArrayList<Node>(nodes.values());
53     }
54
55     public Node getNode(long graphId, long nodeId) throws JsonParseException, JsonMappingException, JAXBException, IOException, MyNotFoundException {
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
63         Node node=manager.getNodeById(nodeId, graphId);
64         if (node == null) {
65             throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId);
66         }
67         return node;
68     }
69
70     public Node updateNode(long graphId, Node node) throws JAXBException, IOException, MyInvalidIdException {
71         if (graphId < 0) {
72             throw new ForbiddenException("Illegal graph id: " + graphId);
73         }
74         if (node.getId() < 0) {
75             throw new ForbiddenException("Illegal node id: " + node.getId());
76         }
77
78         Graph graph=manager.getGraph(graphId);
79         validateNode(graph, node);
80
81         Node n=manager.updateNode(graphId, node, node.getId());
82         validateNode(graph, n);
83
84         return n;
85     }
86
87     public Node removeNode(long graphId, long nodeId) throws JsonParseException, JsonMappingException, JAXBException, IOException {
88         if (graphId < 0) {
89             throw new ForbiddenException("Illegal graph id: " + graphId);
90         }
91         if (nodeId < 0) {
92             throw new ForbiddenException("Illegal node id: " + nodeId);
93         }
94
95         Graph graph=manager.getGraph(graphId);
96         if (graph == null)
97             throw new DataNotFoundException("Graph with id " + graphId + " not found");
98         Node n=manager.deleteNode(graphId, nodeId);
99         return n;
100     }
101
102     public Node addNode(long graphId, Node node) throws JsonParseException, JsonMappingException, JAXBException, IOException, MyInvalidIdException {
103         if (graphId < 0) {
104             throw new ForbiddenException("Illegal graph id: " + graphId);
105         }
106
107         Graph graph=manager.getGraph(graphId);
108         validateNode(graph, node);
109         Node n=manager.addNode(graphId, node);
110         validateNode(graph, n);
111         return n;
112     }
113
114     public Node searchByName(long graphId, String nodeName) throws JsonParseException, JsonMappingException, JAXBException, IOException {
115         if (graphId < 0) {
116             throw new ForbiddenException("Illegal graph id: " + graphId);
117         }
118         Graph graph = manager.getGraph(graphId);
119         if (graph == null)
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))
124                 return node;
125         }
126         return null;
127     }
128
129     public static void validateNode(Graph graph, Node node) throws JsonProcessingException {
130         if (graph == null)
131             throw new BadRequestException("Node validation failed: cannot validate null graph");
132         if (node == null)
133             throw new BadRequestException("Node validation failed: cannot validate null node");
134
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");
139
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");
144
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()
148             + "'");
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);
158             }
159         }
160
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);
167         }
168     }
169
170     public static void validateNodeConfigurationAgainstSchemaFile(Node node, JsonNode configurationJson) {
171         String schemaFileName = node.getFunctional_type() + ".json";
172
173         File schemaFile = new File(System.getProperty("catalina.base") + "/webapps/verigraph/jsonschema/" + schemaFileName);
174
175         if (!schemaFile.exists()) {
176             //if no REST client, try gRPC application
177             schemaFile = new File(System.getProperty("user.dir") + "/jsonschema/" + schemaFileName);
178
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() + "'");
183             }
184         }
185
186         JsonSchema schemaNode = null;
187         try {
188             schemaNode = ValidationUtils.getSchemaNode(schemaFile);
189         }
190         catch (IOException e) {
191             throw new InternalServerErrorException("Unable to load '" + schemaFileName + "' schema file");
192         }
193         catch (ProcessingException e) {
194             throw new InternalServerErrorException("Unable to resolve '"+ schemaFileName
195                     + "' schema file as a schema node");
196         }
197
198         try {
199             ValidationUtils.validateJson(schemaNode, configurationJson);
200         }
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() + "': "
205             + e.getMessage());
206         }
207
208     }
209
210     public Configuration addNodeConfiguration(long graphId, long nodeId, Configuration nodeConfiguration) throws IOException, MyInvalidIdException {
211         if (graphId < 0) {
212             throw new ForbiddenException("Illegal graph id: " + graphId);
213         }
214         if (nodeId < 0) {
215             throw new ForbiddenException("Illegal node id: " + nodeId);
216         }
217
218         Node node=manager.getNodeById(nodeId, graphId);
219         validateNodeConfigurationAgainstSchemaFile(node, nodeConfiguration.getConfiguration());
220         Configuration newConf=manager.updateConfiguration(nodeId, graphId, nodeConfiguration, node);
221         return newConf;
222     }
223 }