Merge "Update spring-boot to 2.2"
[aai/traversal.git] / aai-traversal / src / main / java / org / onap / aai / rest / CQ2GremlinTest.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.aai.rest;
21
22 import java.util.ArrayList;
23 import java.util.Comparator;
24 import java.util.HashSet;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Optional;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.stream.Collectors;
31
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.PUT;
34 import javax.ws.rs.Path;
35 import javax.ws.rs.Produces;
36 import javax.ws.rs.core.Context;
37 import javax.ws.rs.core.HttpHeaders;
38 import javax.ws.rs.core.MediaType;
39 import javax.ws.rs.core.Response;
40 import javax.ws.rs.core.UriInfo;
41
42 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
43 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
44 import org.apache.tinkerpop.gremlin.structure.Graph;
45 import org.apache.tinkerpop.gremlin.structure.T;
46 import org.apache.tinkerpop.gremlin.structure.Vertex;
47 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
48 import org.onap.aai.config.SpringContextAware;
49 import org.onap.aai.exceptions.AAIException;
50 import org.onap.aai.introspection.Loader;
51 import org.onap.aai.introspection.LoaderFactory;
52 import org.onap.aai.introspection.ModelType;
53 import org.onap.aai.rest.db.HttpEntry;
54 import org.onap.aai.rest.search.CustomQueryTestDTO;
55 import org.onap.aai.restcore.RESTAPI;
56 import org.onap.aai.restcore.search.GremlinGroovyShell;
57 import org.onap.aai.restcore.search.GroovyQueryBuilder;
58 import org.onap.aai.serialization.db.EdgeSerializer;
59 import org.onap.aai.serialization.engines.TransactionalGraphEngine;
60 import org.onap.aai.setup.SchemaVersion;
61 import org.onap.aai.setup.SchemaVersions;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64 import org.springframework.beans.factory.annotation.Autowired;
65 import org.springframework.beans.factory.annotation.Value;
66 import org.springframework.http.HttpStatus;
67 import org.springframework.web.bind.annotation.RequestBody;
68
69 import com.beust.jcommander.internal.Lists;
70 import com.beust.jcommander.internal.Maps;
71
72 @Path("/cq2gremlintest")
73 public class CQ2GremlinTest extends RESTAPI {
74
75     private static final Logger LOGGER = LoggerFactory.getLogger(CQ2GremlinTest.class);
76
77     private HttpEntry traversalUriHttpEntry;
78
79     @Autowired
80     protected LoaderFactory loaderFactory;
81
82     @Autowired
83     protected EdgeSerializer rules;
84
85     protected Loader loader;
86     protected GraphTraversalSource gts;
87
88     @Autowired
89     public CQ2GremlinTest(HttpEntry traversalUriHttpEntry,
90         @Value("${schema.uri.base.path}") String basePath) {
91         this.traversalUriHttpEntry = traversalUriHttpEntry;
92
93     }
94
95     @PUT
96     @Path("")
97     @Consumes({MediaType.APPLICATION_JSON})
98     @Produces({MediaType.APPLICATION_JSON})
99     public Response getC2Qgremlin(@RequestBody CustomQueryTestDTO content,
100         @Context HttpHeaders headers, @Context UriInfo info) throws AAIException {
101         if (content == null) {
102             return Response.status(HttpStatus.BAD_REQUEST.value())
103                 .entity("At least one Json payload should be passed").build();
104         }
105         String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
106         String realTime = headers.getRequestHeaders().getFirst("Real-Time");
107         SchemaVersions schemaVersions = SpringContextAware.getBean(SchemaVersions.class);
108         traversalUriHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion());
109         traversalUriHttpEntry.setPaginationParameters("-1", "-1");
110         return processC2UnitTest(content);
111     }
112
113     private Response processC2UnitTest(CustomQueryTestDTO content) {
114
115         TransactionalGraphEngine dbEngine = traversalUriHttpEntry.getDbEngine();
116         Graph graph = TinkerGraph.open();
117         gts = graph.traversal();
118         List<Vertex> expectedVertices = createGraph(content, graph);
119         GremlinGroovyShell shell = new GremlinGroovyShell();
120         loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, new SchemaVersion("v19"));
121         LinkedHashMap<String, Object> params = new LinkedHashMap<>();
122
123         // Adding parameters
124         content.getQueryRequiredProperties().forEach(params::put);
125         content.getQueryOptionalProperties().forEach(params::put);
126
127         String query =
128             new GroovyQueryBuilder().executeTraversal(dbEngine, content.getStoredQuery(), params);
129         query = "g" + query;
130         GraphTraversal<Vertex, Vertex> g = graph.traversal().V();
131         addStartNode(g, content);
132         params.put("g", g);
133
134         // Assertion
135         GraphTraversal<Vertex, Vertex> result =
136             (GraphTraversal<Vertex, Vertex>) shell.executeTraversal(query, params);
137
138         List<Vertex> vertices = result.toList();
139
140         LOGGER.info("Expected result set of vertexes [{}]", convert(expectedVertices));
141         LOGGER.info("Actual Result set of vertexes [{}]", convert(vertices));
142
143         List<Vertex> nonDuplicateExpectedResult = new ArrayList<>(new HashSet<>(expectedVertices));
144         vertices = new ArrayList<>(new HashSet<>(vertices));
145
146         nonDuplicateExpectedResult.sort(Comparator.comparing(vertex -> vertex.id().toString()));
147         vertices.sort(Comparator.comparing(vertex -> vertex.id().toString()));
148
149         // Use this instead of the assertTrue as this provides more useful
150         // debugging information such as this when expected and actual differ:
151         // java.lang.AssertionError: Expected all the vertices to be found
152         // Expected :[v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12]]
153         // Actual :[v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12]]
154         if (nonDuplicateExpectedResult.equals(vertices)) {
155             return Response.ok("Sucessfully executed Junit").build();
156         }
157         return Response.status(400).build();
158
159     }
160
161     private List<Vertex> createGraph(CustomQueryTestDTO content, Graph graph) {
162         Map<String, Vertex> verticesMap = Maps.newLinkedHashMap();
163         // Creating all the Vertices
164         content.getVerticesDtos().forEach(vertex -> {
165             StringBuilder vertexIdentifier = new StringBuilder();
166             List<String> keyValues = Lists.newArrayList();
167             keyValues.add(T.id.toString());
168             keyValues.add(String.format("%02d", verticesMap.size() * 10));
169             AtomicInteger index = new AtomicInteger(0);
170             vertex.forEach((k, v) -> {
171                 if (index.get() == 1)
172                     vertexIdentifier.append(k);
173                 keyValues.add(k);
174                 keyValues.add(v);
175                 index.incrementAndGet();
176             });
177             Vertex graphVertex = graph.addVertex(keyValues.toArray());
178             verticesMap.put(vertexIdentifier.toString(), graphVertex);
179         });
180
181         GraphTraversalSource g = graph.traversal();
182
183         // Creating all the Edges
184         content.getEdgesDtos().forEach(edge -> {
185             String fromId = edge.get("from-id");
186             String toId = edge.get("to-id");
187             boolean treeEdgeIdentifier = !"NONE".equalsIgnoreCase(edge.get("contains-other-v"));
188             Vertex fromVertex = verticesMap.get(fromId);
189             Vertex toVertex = verticesMap.get(toId);
190             try {
191                 if (treeEdgeIdentifier) {
192                     rules.addTreeEdge(g, fromVertex, toVertex);
193                 } else {
194                     rules.addEdge(g, fromVertex, toVertex);
195                 }
196             } catch (AAIException ex) {
197                 LOGGER.warn(ex.toString(), ex);
198             }
199
200         });
201
202         List<Vertex> expectedVertices = Lists.newArrayList();
203         content.getExpectedResultsDtos().getIds()
204             .forEach(vertexId -> expectedVertices.add(verticesMap.get(vertexId)));
205         return expectedVertices;
206     }
207
208     protected void addStartNode(GraphTraversal<Vertex, Vertex> g, CustomQueryTestDTO content) {
209         Optional<LinkedHashMap<String, String>> startNodeVertex = content.getVerticesDtos().stream()
210             .filter(map -> map.containsKey("start-node")).findFirst();
211         if (!startNodeVertex.isPresent()) {
212             throw new IllegalArgumentException("start-node was not specified");
213         }
214         startNodeVertex.get().forEach((k, v) -> {
215             g.has(k, v);
216         });
217     }
218
219     protected String convert(List<Vertex> vertices) {
220         return vertices.stream().map(vertex -> vertex.property("aai-node-type").value().toString())
221             .collect(Collectors.joining(","));
222     }
223
224 }