diff options
31 files changed, 1573 insertions, 484 deletions
diff --git a/aai-traversal/src/main/java/org/onap/aai/TraversalApp.java b/aai-traversal/src/main/java/org/onap/aai/TraversalApp.java index 64a3b44..4d8f4a8 100644 --- a/aai-traversal/src/main/java/org/onap/aai/TraversalApp.java +++ b/aai-traversal/src/main/java/org/onap/aai/TraversalApp.java @@ -179,6 +179,7 @@ public class TraversalApp { } String currentDirectory = System.getProperty("user.dir"); + System.setProperty("aai.service.name", TraversalApp.class.getSimpleName()); if (System.getProperty("AJSC_HOME") == null) { System.setProperty("AJSC_HOME", "."); diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/VersionInterceptor.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/VersionInterceptor.java index df9807c..902d6f0 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/VersionInterceptor.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/VersionInterceptor.java @@ -62,7 +62,7 @@ public class VersionInterceptor extends AAIContainerFilter implements ContainerR String uri = requestContext.getUriInfo().getPath(); - if (uri.startsWith("search") || uri.startsWith("util/echo") || uri.startsWith("tools") || uri.startsWith("recents")) { + if (uri.startsWith("search") || uri.startsWith("util/echo") || uri.startsWith("tools") || uri.startsWith("recents")|| uri.startsWith("cq2gremlin")|| uri.startsWith("cq2gremlintest")) { return; } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java new file mode 100644 index 0000000..dcf8418 --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java @@ -0,0 +1,126 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.rest; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.onap.aai.config.SpringContextAware; +import org.onap.aai.dbmap.DBConnectionType; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.LoaderFactory; +import org.onap.aai.rest.db.HttpEntry; +import org.onap.aai.rest.search.CustomQueryConfigDTO; +import org.onap.aai.rest.search.CustomQueryDTO; +import org.onap.aai.restcore.RESTAPI; +import org.onap.aai.restcore.search.GroovyQueryBuilder; +import org.onap.aai.serialization.db.EdgeSerializer; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.setup.SchemaVersions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RequestBody; + + +@Path("/cq2gremlin") +public class CQ2Gremlin extends RESTAPI { + + private HttpEntry traversalUriHttpEntry; + + + @Autowired + protected LoaderFactory loaderFactory; + + @Autowired + protected EdgeSerializer rules; + + + @Autowired + public CQ2Gremlin( + HttpEntry traversalUriHttpEntry, + @Value("${schema.uri.base.path}") String basePath + ){ + this.traversalUriHttpEntry = traversalUriHttpEntry; + } + + @PUT + @Path("") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response getC2Qgremlin(@RequestBody Map<String, CustomQueryConfigDTO> content,@Context HttpHeaders headers, @Context UriInfo info) { + if(content.size() == 0){ + return Response.status(HttpStatus.BAD_REQUEST.value()).entity("At least one custom query should be passed").build(); + } + return processGremlinQuery(content.values().toArray(new CustomQueryConfigDTO[0])[0], info, headers); + } + + protected Response processGremlinQuery(CustomQueryConfigDTO content, UriInfo info, + HttpHeaders headers) { + try{ + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String realTime = headers.getRequestHeaders().getFirst("Real-Time"); + LinkedHashMap <String, Object> params; + CustomQueryDTO queryDTO = content.getQueryDTO(); + String query = queryDTO.getQuery(); + params = new LinkedHashMap <>(); + + List<String> optionalParameters = queryDTO.getQueryOptionalProperties(); + if (!optionalParameters.isEmpty()){ + for ( String key : optionalParameters ) { + params.put(key, key); + } + } + + List<String> requiredParameters = queryDTO.getQueryRequiredProperties(); + if (!requiredParameters.isEmpty()){ + for ( String key : requiredParameters ) { + params.put(key, key); + } + } + + SchemaVersions schemaVersions = SpringContextAware.getBean(SchemaVersions.class); + DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime); + traversalUriHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalUriHttpEntry.setPaginationParameters("-1", "-1"); + + TransactionalGraphEngine dbEngine = traversalUriHttpEntry.getDbEngine(); + + query = new GroovyQueryBuilder().executeTraversal(dbEngine,query, params); + query = "g" + query; + return Response.ok(query).build(); + } + catch(Exception ex){ + return Response.status(500).entity("Query conversion failed with following reason: " + ex.toString()).build(); + } + + } +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java new file mode 100644 index 0000000..40538be --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java @@ -0,0 +1,235 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.rest; + + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import javax.ws.rs.Consumes; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.onap.aai.config.SpringContextAware; +import org.onap.aai.dbmap.DBConnectionType; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.LoaderFactory; +import org.onap.aai.introspection.ModelType; +import org.onap.aai.rest.db.HttpEntry; +import org.onap.aai.rest.search.CustomQueryTestDTO; +import org.onap.aai.restcore.RESTAPI; +import org.onap.aai.restcore.search.GremlinGroovyShell; +import org.onap.aai.restcore.search.GroovyQueryBuilder; +import org.onap.aai.serialization.db.EdgeSerializer; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.setup.SchemaVersion; +import org.onap.aai.setup.SchemaVersions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RequestBody; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.beust.jcommander.internal.Lists; +import com.beust.jcommander.internal.Maps; + + +@Path("/cq2gremlintest") +public class CQ2GremlinTest extends RESTAPI { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(CQ2GremlinTest.class); + + private HttpEntry traversalUriHttpEntry; + + + @Autowired + protected LoaderFactory loaderFactory; + + @Autowired + protected EdgeSerializer rules; + + protected Loader loader; + protected GraphTraversalSource gts; + + + @Autowired + public CQ2GremlinTest( + HttpEntry traversalUriHttpEntry, + @Value("${schema.uri.base.path}") String basePath + ){ + this.traversalUriHttpEntry = traversalUriHttpEntry; + + } + + @PUT + @Path("") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response getC2Qgremlin(@RequestBody CustomQueryTestDTO content,@Context HttpHeaders headers, @Context UriInfo info) throws AAIException { + if(content == null){ + return Response.status(HttpStatus.BAD_REQUEST.value()).entity("At least one Json payload should be passed").build(); + } + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String realTime = headers.getRequestHeaders().getFirst("Real-Time"); + SchemaVersions schemaVersions = SpringContextAware.getBean(SchemaVersions.class); + DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime); + traversalUriHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion(), type); + traversalUriHttpEntry.setPaginationParameters("-1", "-1"); + return processC2UnitTest(content); + } + + private Response processC2UnitTest(CustomQueryTestDTO content) { + + TransactionalGraphEngine dbEngine = traversalUriHttpEntry.getDbEngine(); + Graph graph = TinkerGraph.open(); + gts = graph.traversal(); + List<Vertex> expectedVertices = createGraph(content, graph); + GremlinGroovyShell shell = new GremlinGroovyShell(); + loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, new SchemaVersion("v16")); + LinkedHashMap <String, Object> params = new LinkedHashMap<>(); + + //Adding parameters + content.getQueryRequiredProperties().forEach((K, V) -> {params.put(K, V);}); + content.getQueryOptionalProperties().forEach((K, V) -> {params.put(K, V);}); + + String query = new GroovyQueryBuilder().executeTraversal(dbEngine, content.getStoredQuery(), params); + query = "g" + query; + GraphTraversal<Vertex, Vertex> g = graph.traversal().V(); + addStartNode(g, content); + params.put("g", g); + + //Assertion + GraphTraversal<Vertex, Vertex> result = (GraphTraversal<Vertex, Vertex>)shell.executeTraversal(query, params); + + List<Vertex> vertices = result.toList(); + + LOGGER.info("Expected result set of vertexes [{}]", convert(expectedVertices)); + LOGGER.info("Actual Result set of vertexes [{}]", convert(vertices)); + + List<Vertex> nonDuplicateExpectedResult = new ArrayList<>(new HashSet<>(expectedVertices)); + vertices = new ArrayList<>(new HashSet<>(vertices)); + + nonDuplicateExpectedResult.sort(Comparator.comparing(vertex -> vertex.id().toString())); + vertices.sort(Comparator.comparing(vertex -> vertex.id().toString())); + + + // Use this instead of the assertTrue as this provides more useful + // debugging information such as this when expected and actual differ: + // java.lang.AssertionError: Expected all the vertices to be found + // Expected :[v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12]] + // 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]] + if(nonDuplicateExpectedResult.equals(vertices)){ + return Response.ok("Sucessfully executed Junit").build(); + } + return Response.status(400).build(); + + } + + private List<Vertex> createGraph(CustomQueryTestDTO content, Graph graph) { + Map<String, Vertex> verticesMap = Maps.newLinkedHashMap(); + //Creating all the Vertices + content.getVerticesDtos().stream().forEach(vertex -> { + StringBuilder vertexIdentifier = new StringBuilder(); + List<String> keyValues = Lists.newArrayList(); + keyValues.add(T.id.toString()); + keyValues.add(String.format("%02d", verticesMap.size() * 10)); + AtomicInteger index = new AtomicInteger(0); + vertex.forEach((K, V) -> { + if(index.get() == 1) + vertexIdentifier.append(V); + keyValues.add(K); + keyValues.add(V); + index.incrementAndGet(); + }); + Vertex graphVertex = graph.addVertex(keyValues.toArray()); + verticesMap.put(vertexIdentifier.toString(), graphVertex); + }); + + GraphTraversalSource g = graph.traversal(); + + //Creating all the Edges + content.getEdgesDtos().stream().forEach(edge -> { + String fromId = edge.get("from-id"); + String toId = edge.get("to-id"); + boolean treeEdgeIdentifier = !"NONE".equalsIgnoreCase(edge.get("contains-other-v")); + Vertex fromVertex = verticesMap.get(fromId); + Vertex toVertex = verticesMap.get(toId); + try{ + if(treeEdgeIdentifier){ + rules.addTreeEdge(g, fromVertex, toVertex); + } + else{ + rules.addEdge(g, fromVertex, toVertex); + } + } catch(AAIException ex){ + LOGGER.warn(ex.toString(), ex); + } + + }); + + + List<Vertex> expectedVertices = Lists.newArrayList(); + content.getExpectedResultsDtos().getIds().stream().forEach(vertexId -> { + expectedVertices.add(verticesMap.get(vertexId)); + }); + return expectedVertices; + } + + protected void addStartNode(GraphTraversal<Vertex, Vertex> g, CustomQueryTestDTO content) { + Optional<LinkedHashMap<String, String>> startNodeVertex = content.getVerticesDtos().stream().filter(map -> map.containsKey("start-node")).findFirst(); + if(!startNodeVertex.isPresent()){ + throw new IllegalArgumentException("start-node was not specified"); + } + startNodeVertex.get().forEach((K, V) -> { + g.has(K, V); + }); + } + + protected String convert(List<Vertex> vertices){ + return vertices + .stream() + .map(vertex -> vertex.property("aai-node-type").value().toString()) + .collect(Collectors.joining(",")); + } + + + +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java b/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java index ad5fffb..2d09636 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java @@ -19,25 +19,11 @@ */ package org.onap.aai.rest; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.Consumes; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.Encoded; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import javax.ws.rs.core.Response.Status; - +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import org.onap.aai.concurrent.AaiCallable; import org.onap.aai.dbmap.DBConnectionType; import org.onap.aai.exceptions.AAIException; @@ -64,11 +50,12 @@ import org.onap.aai.util.TraversalConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; +import java.util.List; +import java.util.concurrent.TimeUnit; @Path("{version: v[1-9][0-9]*|latest}/dsl") public class DslConsumer extends RESTAPI { @@ -90,8 +77,8 @@ public class DslConsumer extends RESTAPI { @Autowired public DslConsumer(HttpEntry traversalUriHttpEntry, DslQueryProcessor dslQueryProcessor, - SchemaVersions schemaVersions, GremlinServerSingleton gremlinServerSingleton, - @Value("${schema.uri.base.path}") String basePath) { + SchemaVersions schemaVersions, GremlinServerSingleton gremlinServerSingleton, + @Value("${schema.uri.base.path}") String basePath) { this.traversalUriHttpEntry = traversalUriHttpEntry; this.dslQueryProcessor = dslQueryProcessor; this.schemaVersions = schemaVersions; diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/AAIDslErrorListener.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/AAIDslErrorListener.java new file mode 100644 index 0000000..26a625a --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/AAIDslErrorListener.java @@ -0,0 +1,34 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.rest.dsl; + +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; +import org.antlr.v4.runtime.misc.ParseCancellationException; + +public class AAIDslErrorListener extends BaseErrorListener { + + @Override + public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) + throws ParseCancellationException { + throw new ParseCancellationException("line " + line + ":" + charPositionInLine + " " + msg); + } +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslListener.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslListener.java index a6be24c..8fd23cc 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslListener.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslListener.java @@ -19,235 +19,239 @@ */ package org.onap.aai.rest.dsl; -import java.util.ArrayList; -import java.util.Deque; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; -import java.util.List; - -import org.antlr.v4.runtime.tree.TerminalNode; - +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.common.collect.Lists; +import org.onap.aai.AAIDslBaseListener; import org.onap.aai.AAIDslParser; -import org.onap.aai.config.SpringContextAware; -import org.onap.aai.edges.EdgeRuleQuery; -import org.onap.aai.edges.enums.EdgeType; +import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.introspection.ModelType; -import org.onap.aai.logging.LogFormatTools; -import org.onap.aai.setup.SchemaVersion; import org.onap.aai.setup.SchemaVersions; import org.springframework.beans.factory.annotation.Autowired; -import org.onap.aai.AAIDslBaseListener; -import org.onap.aai.edges.EdgeIngestor; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * The Class DslListener. */ public class DslListener extends AAIDslBaseListener { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DslQueryProcessor.class); + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DslListener.class); - private final EdgeIngestor edgeRules; + boolean validationFlag = false; + EdgeIngestor edgeIngestor; + Loader loader; - DslContext context = null; - DslQueryBuilder dslBuilder = null; + private Deque<DslQueryBuilder> dslQueryBuilders = new LinkedList<>(); + private Deque<String> traversedNodes = new LinkedList<>(); + private Deque<List<String>> returnedNodes = new LinkedList<>(); + + List<String> traversedEdgeLabels = new LinkedList<>(); /** * Instantiates a new DslListener. */ @Autowired public DslListener(EdgeIngestor edgeIngestor, SchemaVersions schemaVersions, LoaderFactory loaderFactory) { - this.edgeRules = edgeIngestor; - context = new DslContext(); + this.loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); + this.edgeIngestor = edgeIngestor; + } - Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); - dslBuilder = new DslQueryBuilder(edgeIngestor, loader); + public DslQueryBuilder builder() { + return dslQueryBuilders.peekFirst(); } public String getQuery() throws AAIException { + //TODO Change the exception reporting if (!getException().isEmpty()) { LOGGER.error("Exception in the DSL Query" + getException()); throw new AAIException("AAI_6149", getException()); } - return dslBuilder.getQuery().toString(); + + return this.compile(); + } + + public String compile() { + List<String> queries = dslQueryBuilders.stream().map(dslQb -> dslQb.getQuery().toString()).collect(Collectors.toList()); + return String.join("", Lists.reverse(queries)); } public String getException() { - return dslBuilder.getQueryException().toString(); + return builder().getQueryException().toString(); } @Override public void enterAaiquery(AAIDslParser.AaiqueryContext ctx) { - /* - * This is my start-node, have some validations here - */ - context.setStartNodeFlag(true); - dslBuilder.start(); + dslQueryBuilders.push(new DslQueryBuilder(edgeIngestor, loader)); } @Override - public void exitAaiquery(AAIDslParser.AaiqueryContext ctx) { - dslBuilder.end(context); + public void enterStartStatement(AAIDslParser.StartStatementContext ctx) { + builder().start(); } @Override - public void enterDslStatement(AAIDslParser.DslStatementContext ctx) { - if (context.isUnionStart()) { - dslBuilder.startUnion(); + public void exitStartStatement(AAIDslParser.StartStatementContext ctx) { + builder().end(); + if (!traversedNodes.isEmpty()) { + traversedNodes.removeFirst(); } + } @Override - public void exitDslStatement(AAIDslParser.DslStatementContext ctx) { - if (context.isUnionQuery()) { - dslBuilder.comma(context); - context.setUnionStart(true); - } + public void exitLimit(AAIDslParser.LimitContext ctx) { + builder().limit(ctx.num().getText()); } @Override - public void enterSingleNodeStep(AAIDslParser.SingleNodeStepContext ctx) { - try { - /* - * Set the previous Node to current node and get the new current - * node - */ - context.setPreviousNode(context.getCurrentNode()); - context.setCurrentNode(ctx.NODE().getText()); - - if (context.isUnionQuery() || context.isTraversal() || context.isWhereQuery()) { - String oldPreviousNode = context.getPreviousNode(); - - if (context.isUnionStart()) { - String previousNode = context.getUnionStartNodes().peek(); - context.setPreviousNode(previousNode); - - context.setUnionStart(false); - } + public void enterNestedStatement(AAIDslParser.NestedStatementContext ctx) { + dslQueryBuilders.addFirst(new DslQueryBuilder(edgeIngestor, loader)); + builder().startInstance(); + } - dslBuilder.edgeQuery(context); + @Override + public void exitNestedStatement(AAIDslParser.NestedStatementContext ctx) { + int count = 1; + if(!ctx.traversal().isEmpty()) { + count += ctx.traversal().size() ; + } + //TODO so ugly + String resultNode = traversedNodes.peekFirst(); - /* - * Reset is required bcos for union queries im changing the - * context - */ - context.setPreviousNode(oldPreviousNode); + if (!traversedNodes.isEmpty()) { + Stream<Integer> integers = Stream.iterate(0, i -> i + 1); + integers.limit(count) + .forEach(i -> traversedNodes.removeFirst()); + } + List<String> resultNodes = returnedNodes.pop(); + resultNodes.add(resultNode); + returnedNodes.addFirst(resultNodes); + } - } + @Override + public void enterComma(AAIDslParser.CommaContext ctx) { + builder().comma(); + } - else { - dslBuilder.nodeQuery(context); - } + @Override + public void enterVertex(AAIDslParser.VertexContext ctx) { - } catch (AAIException e) { - LOGGER.info("AAIException in DslListener" + e.getMessage()); + if (!traversedNodes.isEmpty()) { + builder().edgeQuery(traversedEdgeLabels, traversedNodes.peekFirst(), ctx.label().getText()); + } else { + builder().nodeQuery(ctx.label().getText()); } + traversedNodes.addFirst(ctx.label().getText()); } @Override - public void exitSingleNodeStep(AAIDslParser.SingleNodeStepContext ctx) { - if (context.isStartNode() && isValidationFlag()) { - try { - dslBuilder.validateFilter(context); - } catch (AAIException e) { - LOGGER.error("AAIException in DslListener" + LogFormatTools.getStackTop(e)); + public void exitVertex(AAIDslParser.VertexContext ctx) { + + /*TODO dont use context */ + if (ctx.getParent() instanceof AAIDslParser.StartStatementContext && isValidationFlag()) { + List<String> allKeys = new ArrayList<>(); + + if (ctx.filter() != null) { + allKeys = ctx.filter().propertyFilter().stream().flatMap( + pf -> pf.key().stream()).map( + e -> e.getText().replaceAll("\'", "")).collect(Collectors.toList()); + } + builder().validateFilter(ctx.label().getText(), allKeys); } - context.setStartNodeFlag(false); - context.setCtx(ctx); - dslBuilder.store(context); + if (ctx.store() != null) { + builder().store(); + } + traversedEdgeLabels = new ArrayList<>(); } - private void generateExitStep() { + @Override + public void enterUnionVertex(AAIDslParser.UnionVertexContext ctx) { + returnedNodes.addFirst(new ArrayList<>()); + builder().union(); } @Override - public void enterUnionQueryStep(AAIDslParser.UnionQueryStepContext ctx) { - - Deque<String> unionStartNodes = context.getUnionStartNodes(); - unionStartNodes.add(context.getCurrentNode()); - - context.setUnionStart(true); - /* - * I may not need this - */ - context.setUnionQuery(true); - dslBuilder.union(context); + public void exitUnionVertex(AAIDslParser.UnionVertexContext ctx) { + String resultNode = returnedNodes.pop().get(0); + traversedNodes.addFirst(resultNode); + builder().endUnion(); + } + @Override + public void enterWhereFilter(AAIDslParser.WhereFilterContext ctx) { + returnedNodes.addFirst(new ArrayList<>()); + builder().where(); } @Override - public void exitUnionQueryStep(AAIDslParser.UnionQueryStepContext ctx) { - context.setUnionStart(false); - context.setUnionQuery(false); - Deque<String> unionStartNodes = context.getUnionStartNodes(); - if (unionStartNodes.peek() != null) { - unionStartNodes.pop(); + public void exitWhereFilter(AAIDslParser.WhereFilterContext ctx) { + if(!returnedNodes.isEmpty()) { + returnedNodes.pop(); } - - dslBuilder.endUnion(context); - + builder().endWhere(); } @Override - public void enterFilterTraverseStep(AAIDslParser.FilterTraverseStepContext ctx) { - context.setWhereQuery(true); - context.setWhereStartNode(context.getCurrentNode()); - dslBuilder.where(context); - + public void enterTraversal(AAIDslParser.TraversalContext ctx) { } @Override - public void exitFilterTraverseStep(AAIDslParser.FilterTraverseStepContext ctx) { - context.setWhereQuery(false); - context.setCurrentNode(context.getWhereStartNode()); - - dslBuilder.endWhere(context); - + public void enterEdge(AAIDslParser.EdgeContext ctx) { } @Override - public void enterFilterStep(AAIDslParser.FilterStepContext ctx) { + public void enterEdgeFilter(AAIDslParser.EdgeFilterContext ctx) { + traversedEdgeLabels = ctx.key().stream().map(value -> value.getText()).collect(Collectors.toList()); - context.setCtx(ctx); - dslBuilder.filter(context); } @Override - public void exitFilterStep(AAIDslParser.FilterStepContext ctx) { - // For now do nothing - } + public void enterFilter(AAIDslParser.FilterContext ctx) { - @Override - public void enterTraverseStep(AAIDslParser.TraverseStepContext ctx) { - context.setTraversal(true); } @Override - public void exitTraverseStep(AAIDslParser.TraverseStepContext ctx) { - context.setTraversal(false); + public void enterPropertyFilter(AAIDslParser.PropertyFilterContext ctx) { + + List<AAIDslParser.KeyContext> valueList = ctx.key(); + String filterKey = valueList.get(0).getText(); + + boolean isNot = ctx.not() != null && !ctx.not().isEmpty(); + List<AAIDslParser.NumContext> numberValues = ctx.num(); + + /* + * Add all String values + */ + List<String> values = valueList.stream().filter(value -> !filterKey.equals(value.getText())) + .map(value -> "'" + value.getText().replace("'", "") + "'").collect(Collectors.toList()); + /* + * Add all numeric values + */ + values.addAll(numberValues.stream().filter(value -> !filterKey.equals(value.getText())) + .map(value -> value.getText()).collect(Collectors.toList())); + + builder().filter(isNot, traversedNodes.peekFirst(), filterKey, values); + } - @Override - public void enterLimitStep(AAIDslParser.LimitStepContext ctx) { - context.setCtx(ctx); - dslBuilder.limit(context); + public boolean isValidationFlag() { + return validationFlag; } - + public void setValidationFlag(boolean validationFlag) { - this.context.setValidationFlag(validationFlag); - } - - public boolean isValidationFlag() { - return this.context.isValidationFlag(); + this.validationFlag = validationFlag; } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslQueryBuilder.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslQueryBuilder.java index fce8a98..6817cf7 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslQueryBuilder.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslQueryBuilder.java @@ -19,224 +19,247 @@ */ package org.onap.aai.rest.dsl; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import org.antlr.v4.runtime.tree.TerminalNode; -import org.apache.tinkerpop.gremlin.structure.Direction; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.onap.aai.AAIDslBaseListener; -import org.onap.aai.AAIDslParser; +import com.google.common.base.Joiner; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.edges.EdgeRule; import org.onap.aai.edges.EdgeRuleQuery; import org.onap.aai.edges.enums.EdgeType; -import org.onap.aai.exceptions.AAIException; +import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; +import org.onap.aai.schema.enums.PropertyMetadata; -import com.jcabi.log.Logger; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; public class DslQueryBuilder { - private StringBuilder query; - private StringBuilder queryException; - private final EdgeIngestor edgeRules; - private final Loader loader; - - public DslQueryBuilder(EdgeIngestor edgeIngestor, Loader loader) { - this.edgeRules = edgeIngestor; - this.loader = loader; - query = new StringBuilder(); - queryException = new StringBuilder(); - } - - public StringBuilder getQuery() { - return query; - } - - public void setQuery(StringBuilder query) { - this.query = query; - } - - public StringBuilder getQueryException() { - return queryException; - } - - public void setQueryException(StringBuilder queryException) { - this.queryException = queryException; - } - - public DslQueryBuilder start() { - query.append("builder"); - return this; - } - - public DslQueryBuilder startUnion() { - query.append("builder.newInstance()"); - return this; - } - - public DslQueryBuilder end(DslContext context) { - query.append(".cap('x').unfold().dedup()").append(context.getLimitQuery()); - return this; - } - - public DslQueryBuilder nodeQuery(DslContext context) { - query.append(".getVerticesByProperty('aai-node-type', '").append(context.getCurrentNode()).append("')"); - if(context.isStartNode() && context.getStartNode().isEmpty()) - context.setStartNode(context.getCurrentNode()); - return this; - } - - public DslQueryBuilder edgeQuery(DslContext context) throws AAIException { - EdgeRuleQuery.Builder baseQ = new EdgeRuleQuery.Builder(context.getPreviousNode(), context.getCurrentNode()); - String edgeType = ""; - if (!edgeRules.hasRule(baseQ.build())) { - throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + context.getPreviousNode() - + ", " + context.getCurrentNode()); - } else if (edgeRules.hasRule(baseQ.edgeType(EdgeType.TREE).build())) { - edgeType = "EdgeType.TREE"; - } else if (edgeRules.hasRule(baseQ.edgeType(EdgeType.COUSIN).build())) { - edgeType = "EdgeType.COUSIN"; - } else - edgeType = "EdgeType.COUSIN"; - - query.append(".createEdgeTraversal(").append(edgeType).append(", '").append(context.getPreviousNode()) - .append("','").append(context.getCurrentNode()).append("')"); - - return this; - } - - public DslQueryBuilder where(DslContext context) { - query.append(".where(builder.newInstance()"); - return this; - } - - public DslQueryBuilder endWhere(DslContext context) { - query.append(")"); - return this; - } - - public DslQueryBuilder endUnion(DslContext context) { - /* - * Need to delete the last comma - */ - if (query.toString().endsWith(",")) { - query.deleteCharAt(query.length() - 1); - } - query.append(")"); - return this; - } - - public DslQueryBuilder limit(DslContext context) { - /* - * limit queries are strange - You have to append in the end - */ - AAIDslParser.LimitStepContext ctx = (AAIDslParser.LimitStepContext) context.getCtx(); - context.setLimitQuery(new StringBuilder(".limit(").append(ctx.NODE().getText()).append(")")); - return this; - } - - public DslQueryBuilder filter(DslContext context) { - return this.filterPropertyStart(context).filterPropertyKeys(context).filterPropertyEnd(); - - } - - public DslQueryBuilder filterPropertyStart(DslContext context) { - AAIDslParser.FilterStepContext ctx = (AAIDslParser.FilterStepContext) context.getCtx(); - if (ctx.NOT() != null && ctx.NOT().getText().equals("!")) - query.append(".getVerticesExcludeByProperty("); - else - query.append(".getVerticesByProperty("); - - return this; - - } - - public DslQueryBuilder filterPropertyEnd() { - query.append(")"); - return this; - - } - - public DslQueryBuilder validateFilter(DslContext context) throws AAIException { - Introspector obj = loader.introspectorFromName(context.getStartNode()); - if(context.getStartNodeKeys().isEmpty()){ - queryException.append("No keys sent. Valid keys for " + context.getStartNode() + " are " - + String.join(",", obj.getIndexedProperties())); - return this; - } - boolean notIndexed = context.getStartNodeKeys().stream() - .filter((prop) -> obj.getIndexedProperties().contains(prop)).collect(Collectors.toList()).isEmpty(); - if (notIndexed) - queryException.append("Non indexed keys sent. Valid keys for " + context.getStartNode() + " " - + String.join(",", obj.getIndexedProperties())); - - return this; - } - - public DslQueryBuilder filterPropertyKeys(DslContext context) { - AAIDslParser.FilterStepContext ctx = (AAIDslParser.FilterStepContext) context.getCtx(); - final String key = ctx.KEY(0).getText(); - /* - * This key should be indexed if it is start node - */ - if (context.isStartNode() && context.getStartNodeKeys().isEmpty()) { - // check if key is not indexed, then throw exception - context.getStartNodeKeys().add(key.replaceAll("'", "")); - } - - query.append(key); - List<TerminalNode> nodes = ctx.KEY(); - List<TerminalNode> numberValues = ctx.NODE(); - /* - * Add all String values - */ - List<String> valuesArray = nodes.stream().filter((node) -> !key.equals(node.getText())) - .map((node) -> "'" + node.getText().replace("'", "").trim() + "'").collect(Collectors.toList()); - - /* - * Add all numeric values - */ - valuesArray.addAll(numberValues.stream().filter((node) -> !key.equals(node.getText()) ) - .map((node) -> node.getText()).collect(Collectors.toList())); - - - /* - * The whole point of doing this to separate P.within from key-value - * search For a list of values QB uses P.within For just a single value - * QB uses key,value check - */ - if (nodes.size() > 2) { - String values = String.join(",", valuesArray); - query.append(",").append(" new ArrayList<>(Arrays.asList(" + values.toString() + "))"); - } else { - if (!valuesArray.isEmpty()) - query.append(",").append(valuesArray.get(0).toString()); - } - return this; - } - - public DslQueryBuilder union(DslContext context) { - query.append(".union("); - return this; - } - - public DslQueryBuilder store(DslContext context) { - AAIDslParser.SingleNodeStepContext ctx = (AAIDslParser.SingleNodeStepContext) context.getCtx(); - if (ctx.STORE() != null && ctx.STORE().getText().equals("*")) { - query.append(".store('x')"); - } - return this; - - } - - public DslQueryBuilder comma(DslContext context) { - query.append(","); - return this; - - } + private final EdgeIngestor edgeRules; + private final Loader loader; + private StringBuilder query; + private StringBuilder queryException; + + public DslQueryBuilder(EdgeIngestor edgeIngestor, Loader loader) { + this.edgeRules = edgeIngestor; + this.loader = loader; + query = new StringBuilder(); + queryException = new StringBuilder(); + } + + public StringBuilder getQuery() { + return query; + } + + public void setQuery(StringBuilder query) { + this.query = query; + } + + public StringBuilder getQueryException() { + return queryException; + } + + public void setQueryException(StringBuilder queryException) { + this.queryException = queryException; + } + + public DslQueryBuilder start() { + query.append("builder"); + return this; + } + + /* + * DSL always dedupes the results + */ + public DslQueryBuilder end() { + query.append(".cap('x').unfold().dedup()"); + return this; + } + + public DslQueryBuilder nodeQuery(String node) { + query.append(".getVerticesByProperty('aai-node-type', '").append(node).append("')"); + return this; + } + + public DslQueryBuilder edgeQuery(List<String> edgeLabels, String aNode, String bNode) { + //TODO : change this for fuzzy search. + + String edgeType = ""; + String edgeLabelsClause = ""; + String edgeTraversalClause = ".createEdgeTraversal("; + + + if (!edgeLabels.isEmpty()) { + edgeTraversalClause = ".createEdgeTraversalWithLabels("; + edgeLabelsClause = String.join("", ", new ArrayList<>(Arrays.asList(", Joiner.on(",").join(edgeLabels), "))"); + } + + EdgeRuleQuery.Builder baseQ = new EdgeRuleQuery.Builder(aNode, bNode); + Multimap<String, EdgeRule> rules = ArrayListMultimap.create(); + try { + //TODO chnage this - ugly + if (edgeLabels.isEmpty()) { + rules.putAll(edgeRules.getRules(baseQ.build())); + } else { + edgeLabels.stream().forEach(label -> { + try { + rules.putAll(edgeRules.getRules(baseQ.label(label).build())); + } catch (EdgeRuleNotFoundException e) { + queryException.append("AAI_6120" + "No EdgeRule found for passed nodeTypes: " + aNode + + ", " + bNode + label); + + } + }); + + } + } catch (EdgeRuleNotFoundException e) { + if (!edgeLabels.isEmpty()) { + queryException.append("AAI_6120" + "No EdgeRule found for passed nodeTypes: " + aNode + + ", " + bNode + edgeLabels.stream().toString()); + } + else { + queryException.append("AAI_6120" + "No EdgeRule found for passed nodeTypes: " + aNode + + ", " + bNode); + } + return this; + } + + if (rules.isEmpty() || rules.keys().isEmpty()) { + queryException.append("AAI_6120" + "No EdgeRule found for passed nodeTypes: " + aNode + + ", " + bNode); + } else { + if (edgeLabels.isEmpty()) { + if (edgeRules.hasRule(baseQ.edgeType(EdgeType.TREE).build())) { + edgeType = "EdgeType.TREE" + ","; + } + if (edgeRules.hasRule(baseQ.edgeType(EdgeType.COUSIN).build())) { + if (edgeType.isEmpty()) { + edgeType = "EdgeType.COUSIN" + ","; + } else { + edgeType = ""; + } + } + } + } + + query.append(edgeTraversalClause).append(edgeType).append(" '").append(aNode) + .append("','").append(bNode).append("'").append(edgeLabelsClause).append(")"); + + return this; + } + + + public DslQueryBuilder where() { + query.append(".where("); + return this; + } + + public DslQueryBuilder endWhere() { + query.append(")"); + return this; + } + + public DslQueryBuilder limit(String limit) { + query.append(".limit(").append(limit).append(")"); + return this; + } + + public DslQueryBuilder filter(boolean isNot, String node, String key, List<String> values) { + return this.filterPropertyStart(isNot).filterPropertyKeys(node, key, values).filterPropertyEnd(); + } + + public DslQueryBuilder filterPropertyStart(boolean isNot) { + if (isNot) { + query.append(".getVerticesExcludeByProperty("); + } else { + query.append(".getVerticesByProperty("); + } + return this; + } + + public DslQueryBuilder filterPropertyEnd() { + query.append(")"); + return this; + } + + public DslQueryBuilder validateFilter(String node, List<String> keys) { + try { + Introspector obj = loader.introspectorFromName(node); + if (keys.isEmpty()) { + queryException.append("No keys sent. Valid keys for " + node + " are " + + String.join(",", obj.getIndexedProperties())); + return this; + } + + boolean notIndexed = keys.stream() + .filter(prop -> obj.getIndexedProperties().contains(prop)).collect(Collectors.toList()).isEmpty(); + + if (notIndexed) { + queryException.append("Non indexed keys sent. Valid keys for " + node + " " + + String.join(",", obj.getIndexedProperties())); + } + } catch (AAIUnknownObjectException e) { + queryException.append("Unknown Object being referenced by the query" + node); + } + return this; + + } + + public DslQueryBuilder filterPropertyKeys(String node, String key, List<String> values) { + try { + Introspector obj = loader.introspectorFromName(node); + + Optional<String> alias = obj.getPropertyMetadata(key, PropertyMetadata.DB_ALIAS); + if (alias.isPresent()) { + key = alias.get(); + } + query.append(key); + + if (!values.isEmpty()) { + if (values.size() > 1) { + String valuesArray = String.join(",", values); + query.append(",").append(" new ArrayList<>(Arrays.asList(" + valuesArray + "))"); + } else { + query.append(",").append(values.get(0)); + } + } + } catch (AAIUnknownObjectException e) { + queryException.append("Unknown Object being referenced by the query" + node); + } + return this; + } + + public DslQueryBuilder union() { + query.append(".union("); + return this; + } + + public DslQueryBuilder endUnion() { + query.append(")"); + return this; + } + + public DslQueryBuilder store() { + query.append(".store('x')"); + return this; + } + + public DslQueryBuilder startInstance() { + query.append("builder.newInstance()"); + return this; + } + + public DslQueryBuilder endInstance() { + return this; + } + + public DslQueryBuilder comma() { + query.append(","); + return this; + } + + } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslQueryProcessor.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslQueryProcessor.java index d9ce63e..a3978fd 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslQueryProcessor.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslQueryProcessor.java @@ -19,25 +19,23 @@ */ package org.onap.aai.rest.dsl; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.misc.ParseCancellationException; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTreeWalker; - import org.onap.aai.AAIDslLexer; import org.onap.aai.AAIDslParser; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.rest.dsl.DslListener; -import org.antlr.v4.runtime.Token; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; import org.springframework.beans.factory.annotation.Autowired; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + + /** * The Class DslQueryProcessor. */ @@ -60,18 +58,23 @@ public class DslQueryProcessor { // Create a lexer from the input CharStream AAIDslLexer lexer = new AAIDslLexer(CharStreams.fromStream(stream, StandardCharsets.UTF_8)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new AAIDslErrorListener()); // Get a list of tokens pulled from the lexer CommonTokenStream tokens = new CommonTokenStream(lexer); // Parser that feeds off of the tokens buffer AAIDslParser parser = new AAIDslParser(tokens); + parser.removeErrorListeners(); // remove ConsoleErrorListener + parser.addErrorListener(new AAIDslErrorListener()); dslListener.setValidationFlag(isValidationFlag()); // Specify our entry point ParseTree ptree = parser.aaiquery(); LOGGER.info("QUERY-interim" + ptree.toStringTree(parser)); + // Walk it and attach our listener ParseTreeWalker walker = new ParseTreeWalker(); walker.walk(dslListener, ptree); @@ -83,8 +86,10 @@ public class DslQueryProcessor { * */ return dslListener.getQuery(); - } catch (AAIException e) { - throw new AAIException("AAI_6149", "Error while processing the query :" + e.getMessage()); + } catch(ParseCancellationException e){ + throw new AAIException("AAI_6149", "DSL Syntax Error while processing the query :" + e.getMessage()); + } catch(AAIException e) { + throw new AAIException("AAI_6149", "DSL Syntax Error while processing the query :" + e.getMessage()); } catch (Exception e) { throw new AAIException("AAI_6149","Error while processing the query :" + e.getMessage()); } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryConfigDTO.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryConfigDTO.java new file mode 100644 index 0000000..30d8d30 --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryConfigDTO.java @@ -0,0 +1,70 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.rest.search; + +/*- + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import org.springframework.util.StringUtils; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CustomQueryConfigDTO { + + @JsonProperty("stored-query") + private String storedQuery; + @JsonProperty("query") + private CustomQueryDTO queryDTO; + + public CustomQueryDTO getQueryDTO() { + if(queryDTO == null) + queryDTO = new CustomQueryDTO(); + if (!StringUtils.isEmpty(storedQuery)) { + queryDTO.setQuery(storedQuery); + } + return queryDTO; + } + + public void setQueryDTO(CustomQueryDTO query) { + this.queryDTO = query; + } + + public void setStoredQuery(String storedQuery) { + this.storedQuery = storedQuery; + } + +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryDTO.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryDTO.java new file mode 100644 index 0000000..16b1430 --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryDTO.java @@ -0,0 +1,56 @@ +package org.onap.aai.rest.search; + +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.Lists; + +public class CustomQueryDTO { + + private String query; + @JsonProperty("optional-properties") + private List<String> queryOptionalProperties = Lists.newArrayList(); + @JsonProperty("required-properties") + private List<String> queryRequiredProperties = Lists.newArrayList();; + + public void setQuery(String query) { + this.query = query; + } + public String getQuery() { + return this.query; + } + + public void setQueryOptionalProperties( List<String> queryOptionalProperties) { + this.queryOptionalProperties = queryOptionalProperties; + } + public List<String> getQueryOptionalProperties( ) { + return queryOptionalProperties; + } + public void setQueryRequiredProperties( List<String> queryRequiredProperties) { + this.queryRequiredProperties = queryRequiredProperties; + } + public List<String> getQueryRequiredProperties( ) { + return queryRequiredProperties; + } + +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryTestDTO.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryTestDTO.java new file mode 100644 index 0000000..cdc9d15 --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryTestDTO.java @@ -0,0 +1,121 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.rest.search; + +/*- + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.beust.jcommander.internal.Maps; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CustomQueryTestDTO { + + + @JsonProperty("stored-query") + private String storedQuery; + + @JsonProperty("vertices") + private List<LinkedHashMap<String, String>> verticesDtos; + + @JsonProperty("edges") + private List<LinkedHashMap<String, String>> edgesDtos; + + @JsonProperty("optional-properties") + private Map<String, String> queryOptionalProperties = Maps.newHashMap(); + + @JsonProperty("required-properties") + private Map<String, String> queryRequiredProperties = Maps.newHashMap(); + + @JsonProperty("expected-result") + private ExpectedResultsDto expectedResultsDtos; + + public String getStoredQuery() { + return storedQuery; + } + + public void setStoredQuery(String storedQuery) { + this.storedQuery = storedQuery; + } + + public List<LinkedHashMap<String, String>> getVerticesDtos() { + return verticesDtos; + } + + public void setVerticesDtos(List<LinkedHashMap<String, String>> verticesDtos) { + this.verticesDtos = verticesDtos; + } + + public List<LinkedHashMap<String, String>> getEdgesDtos() { + return edgesDtos; + } + + public void setEdgesDtos(List<LinkedHashMap<String, String>> edgesDtos) { + this.edgesDtos = edgesDtos; + } + + public Map<String, String> getQueryOptionalProperties() { + return queryOptionalProperties; + } + + public void setQueryOptionalProperties( + Map<String, String> queryOptionalProperties) { + this.queryOptionalProperties = queryOptionalProperties; + } + + public Map<String, String> getQueryRequiredProperties() { + return queryRequiredProperties; + } + + public void setQueryRequiredProperties( + Map<String, String> queryRequiredProperties) { + this.queryRequiredProperties = queryRequiredProperties; + } + + public ExpectedResultsDto getExpectedResultsDtos() { + return expectedResultsDtos; + } + + public void setExpectedResultsDtos(ExpectedResultsDto expectedResultsDtos) { + this.expectedResultsDtos = expectedResultsDtos; + } + + +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/ExpectedResultsDto.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/ExpectedResultsDto.java new file mode 100644 index 0000000..9c4c3b0 --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/ExpectedResultsDto.java @@ -0,0 +1,39 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.rest.search; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ExpectedResultsDto { + @JsonProperty("ids") + List<String> ids; + + public List<String> getIds() { + return ids; + } + + public void setIds(List<String> ids) { + this.ids = ids; + } + +} diff --git a/aai-traversal/src/main/java/org/onap/aai/web/JerseyConfiguration.java b/aai-traversal/src/main/java/org/onap/aai/web/JerseyConfiguration.java index 231c82b..ab3c9fd 100644 --- a/aai-traversal/src/main/java/org/onap/aai/web/JerseyConfiguration.java +++ b/aai-traversal/src/main/java/org/onap/aai/web/JerseyConfiguration.java @@ -22,6 +22,8 @@ package org.onap.aai.web; import org.glassfish.jersey.filter.LoggingFilter; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.servlet.ServletProperties; +import org.onap.aai.rest.CQ2Gremlin; +import org.onap.aai.rest.CQ2GremlinTest; import org.onap.aai.rest.DslConsumer; import org.onap.aai.rest.QueryConsumer; import org.onap.aai.rest.RecentAPIConsumer; @@ -37,6 +39,7 @@ import org.springframework.stereotype.Component; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerResponseFilter; + import java.util.List; import java.util.Set; import java.util.logging.Logger; @@ -60,6 +63,8 @@ public class JerseyConfiguration extends ResourceConfig { register(RecentAPIConsumer.class); register(DslConsumer.class); register(EchoResponse.class); + register(CQ2Gremlin.class); + register(CQ2GremlinTest.class); //Request Filters registerFiltersForRequests(); diff --git a/aai-traversal/src/main/resources/antlr4/org/onap/aai/AAIDsl.g4 b/aai-traversal/src/main/resources/antlr4/org/onap/aai/AAIDsl.g4 index cf34571..78162f5 100644 --- a/aai-traversal/src/main/resources/antlr4/org/onap/aai/AAIDsl.g4 +++ b/aai-traversal/src/main/resources/antlr4/org/onap/aai/AAIDsl.g4 @@ -1,29 +1,41 @@ /** - * Define a grammar called AAIDsl + * Define a parser grammar called AAIDsl */ grammar AAIDsl; +aaiquery: startStatement limit?; -aaiquery: dslStatement; +startStatement: (vertex ) (traversal)* ; +nestedStatement: (vertex|unionVertex ) (traversal)* ; -dslStatement: (singleNodeStep ) (traverseStep )* limitStep*; +vertex: label store? (filter)?; -unionQueryStep: LBRACKET dslStatement ( COMMA (dslStatement))* RBRACKET; +traversal: (edge (vertex|unionVertex)); -traverseStep: (TRAVERSE ( singleNodeStep | unionQueryStep)); +filter: (propertyFilter)* whereFilter?; +propertyFilter: (not? '(' key (',' (key | num))* ')'); -singleNodeStep: NODE STORE? (filterStep | filterTraverseStep)*; +whereFilter: (not? '(' edge nestedStatement ')' ); -filterStep: NOT? (LPAREN KEY (COMMA (KEY | NODE))* RPAREN); -filterTraverseStep: (LPAREN traverseStep* RPAREN); +unionVertex: '[' ( (edgeFilter)* nestedStatement ( comma ( (edgeFilter)* nestedStatement))*) ']'; -limitStep: LIMIT NODE; +comma: ','; +edge: TRAVERSE (edgeFilter)*; +edgeFilter: '(' key (',' key )* ')'; -LIMIT: 'LIMIT'; -NODE: ID; +num: NUM; +limit: LIMIT num; +label: (ID | NUM )+; +key: KEY; -KEY: ['] (ID | ' ')* ['] ; +store: STORE; +not: NOT; +LIMIT: 'LIMIT'|'limit'; +NUM: (DIGIT)+; + +/*NODE: (ID | NUM )+;*/ +KEY : '\'' ( ~['\r\n] )*? '\''; AND: [&]; @@ -33,29 +45,18 @@ OR: [|]; TRAVERSE: [>] ; -LPAREN: [(]; - -RPAREN: [)]; - -COMMA: [,] ; - EQUAL: [=]; -LBRACKET: [[]; - -RBRACKET: [\]]; - NOT: [!]; -VALUE: [DIGIT]+; - fragment LOWERCASE : [a-z] ; fragment UPPERCASE : [A-Z] ; fragment DIGIT : [0-9] ; +fragment ESC : '\\' . ; +fragment ID_SPECIALS: [-:_]; + ID - : ( LOWERCASE | UPPERCASE | DIGIT) ( LOWERCASE | UPPERCASE | DIGIT | '-' | '.' | '_' | '/')* + : ( LOWERCASE | UPPERCASE | DIGIT | ID_SPECIALS) ; WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines - - diff --git a/aai-traversal/src/main/resources/etc/appprops/aaiconfig.properties b/aai-traversal/src/main/resources/etc/appprops/aaiconfig.properties index a07e985..b94c3b1 100644 --- a/aai-traversal/src/main/resources/etc/appprops/aaiconfig.properties +++ b/aai-traversal/src/main/resources/etc/appprops/aaiconfig.properties @@ -31,23 +31,23 @@ aai.transaction.logging.get=true aai.transaction.logging.post=true aai.server.url.base=https://localhost:8443/aai/ -aai.server.url=https://localhost:8443/aai/v15/ +aai.server.url=https://localhost:8443/aai/v16/ aai.global.callback.url=https://localhost:8443/aai/ -aai.notification.current.version=v15 +aai.notification.current.version=v16 aai.notificationEvent.default.status=UNPROCESSED aai.notificationEvent.default.eventType=AAI-EVENT aai.notificationEvent.default.domain=devINT1 aai.notificationEvent.default.sourceName=aai aai.notificationEvent.default.sequenceNumber=0 aai.notificationEvent.default.severity=NORMAL -aai.notificationEvent.default.version=v15 +aai.notificationEvent.default.version=v16 # This one lets us enable/disable resource-version checking on updates/deletes aai.resourceversion.enableflag=true # This will specify how deep the stack trace should be logged aai.logging.maxStackTraceEntries=10 -aai.default.api.version=v15 +aai.default.api.version=v16 # Used by Model-processing code aai.model.query.resultset.maxcount=50 diff --git a/aai-traversal/src/main/resources/retired.properties b/aai-traversal/src/main/resources/retired.properties index 2261713..2be5d88 100644 --- a/aai-traversal/src/main/resources/retired.properties +++ b/aai-traversal/src/main/resources/retired.properties @@ -1,5 +1,5 @@ # Retired properties retired.api.pattern.list=\ - ^/aai/v[2-7]+/.*$\ + ^/aai/v[2-9]+/.*$\ retired.api.all.versions=
\ No newline at end of file diff --git a/aai-traversal/src/test/java/org/onap/aai/AAIGremlinQueryTest.java b/aai-traversal/src/test/java/org/onap/aai/AAIGremlinQueryTest.java index 0a9ec97..7f5b1d8 100644 --- a/aai-traversal/src/test/java/org/onap/aai/AAIGremlinQueryTest.java +++ b/aai-traversal/src/test/java/org/onap/aai/AAIGremlinQueryTest.java @@ -138,7 +138,7 @@ public class AAIGremlinQueryTest { String authorization = Base64.getEncoder().encodeToString("AAI:AAI".getBytes("UTF-8")); headers.add("Authorization", "Basic " + authorization); - baseUrl = "https://localhost:" + randomPort; + baseUrl = "http://localhost:" + randomPort; } @Test diff --git a/aai-traversal/src/test/java/org/onap/aai/QueryParameterTest.java b/aai-traversal/src/test/java/org/onap/aai/QueryParameterTest.java index 3956b70..76a1277 100644 --- a/aai-traversal/src/test/java/org/onap/aai/QueryParameterTest.java +++ b/aai-traversal/src/test/java/org/onap/aai/QueryParameterTest.java @@ -163,7 +163,7 @@ public class QueryParameterTest { String authorization = Base64.getEncoder().encodeToString("AAI:AAI".getBytes("UTF-8")); headers.add("Authorization", "Basic " + authorization); - baseUrl = "https://localhost:" + randomPort; + baseUrl = "http://localhost:" + randomPort; } @Test diff --git a/aai-traversal/src/test/java/org/onap/aai/SubgraphPruneTest.java b/aai-traversal/src/test/java/org/onap/aai/SubgraphPruneTest.java index efb9e89..bc43979 100644 --- a/aai-traversal/src/test/java/org/onap/aai/SubgraphPruneTest.java +++ b/aai-traversal/src/test/java/org/onap/aai/SubgraphPruneTest.java @@ -106,7 +106,7 @@ public class SubgraphPruneTest { String authorization = Base64.getEncoder().encodeToString("AAI:AAI".getBytes("UTF-8")); headers.add("Authorization", "Basic " + authorization); - baseUrl = "https://localhost:" + randomPort; + baseUrl = "http://localhost:" + randomPort; } @Test diff --git a/aai-traversal/src/test/java/org/onap/aai/TraversalTestConfiguration.java b/aai-traversal/src/test/java/org/onap/aai/TraversalTestConfiguration.java index 46e6be7..552feb6 100644 --- a/aai-traversal/src/test/java/org/onap/aai/TraversalTestConfiguration.java +++ b/aai-traversal/src/test/java/org/onap/aai/TraversalTestConfiguration.java @@ -58,30 +58,35 @@ public class TraversalTestConfiguration { @Bean RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception { - char[] trustStorePassword = env.getProperty("server.ssl.trust-store-password").toCharArray(); - char[] keyStorePassword = env.getProperty("server.ssl.key-store-password").toCharArray(); + RestTemplate restTemplate = null; - String keyStore = env.getProperty("server.ssl.key-store"); - String trustStore = env.getProperty("server.ssl.trust-store"); + if(env.acceptsProfiles("one-way-ssl", "two-way-ssl")) { + char[] trustStorePassword = env.getProperty("server.ssl.trust-store-password").toCharArray(); + char[] keyStorePassword = env.getProperty("server.ssl.key-store-password").toCharArray(); - SSLContextBuilder sslContextBuilder = SSLContextBuilder.create(); + String keyStore = env.getProperty("server.ssl.key-store"); + String trustStore = env.getProperty("server.ssl.trust-store"); + SSLContextBuilder sslContextBuilder = SSLContextBuilder.create(); - if(env.acceptsProfiles("two-way-ssl")){ - sslContextBuilder = sslContextBuilder.loadKeyMaterial(loadPfx(keyStore, keyStorePassword), keyStorePassword); - } + if (env.acceptsProfiles("two-way-ssl")) { + sslContextBuilder = sslContextBuilder.loadKeyMaterial(loadPfx(keyStore, keyStorePassword), keyStorePassword); + } - SSLContext sslContext = sslContextBuilder - .loadTrustMaterial(ResourceUtils.getFile(trustStore), trustStorePassword) - .build(); + SSLContext sslContext = sslContextBuilder + .loadTrustMaterial(ResourceUtils.getFile(trustStore), trustStorePassword) + .build(); - HttpClient client = HttpClients.custom() - .setSSLContext(sslContext) - .setSSLHostnameVerifier((s, sslSession) -> true) - .build(); + HttpClient client = HttpClients.custom() + .setSSLContext(sslContext) + .setSSLHostnameVerifier((s, sslSession) -> true) + .build(); - RestTemplate restTemplate = builder - .requestFactory(new HttpComponentsClientHttpRequestFactory(client)) - .build(); + restTemplate = builder + .requestFactory(new HttpComponentsClientHttpRequestFactory(client)) + .build(); + }else { + restTemplate = builder.build(); + } restTemplate.setErrorHandler(new ResponseErrorHandler() { @Override diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/AbstractSpringRestTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/AbstractSpringRestTest.java index 7235fa3..b767dbb 100644 --- a/aai-traversal/src/test/java/org/onap/aai/rest/AbstractSpringRestTest.java +++ b/aai-traversal/src/test/java/org/onap/aai/rest/AbstractSpringRestTest.java @@ -99,7 +99,7 @@ public abstract class AbstractSpringRestTest { String authorization = Base64.getEncoder().encodeToString("AAI:AAI".getBytes("UTF-8")); headers.add("Authorization", "Basic " + authorization); httpEntity = new HttpEntity(headers); - baseUrl = "https://localhost:" + randomPort; + baseUrl = "http://localhost:" + randomPort; } /* diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/BadQueryFormatTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/BadQueryFormatTest.java index a566499..5edf12d 100644 --- a/aai-traversal/src/test/java/org/onap/aai/rest/BadQueryFormatTest.java +++ b/aai-traversal/src/test/java/org/onap/aai/rest/BadQueryFormatTest.java @@ -84,7 +84,7 @@ public class BadQueryFormatTest { String authorization = Base64.getEncoder().encodeToString("AAI:AAI".getBytes("UTF-8")); headers.add("Authorization", "Basic " + authorization); - baseUrl = "https://localhost:" + randomPort; + baseUrl = "http://localhost:" + randomPort; } @Test diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java index 347e21b..e4576ae 100644 --- a/aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java +++ b/aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java @@ -107,7 +107,7 @@ public class DslConsumerTest extends AbstractSpringRestTest { httpEntity = new HttpEntity(payload, headers); responseEntity = restTemplate.exchange(baseUrl + endpoint, HttpMethod.PUT, httpEntity, String.class); - assertEquals("Expected the response to be 400", HttpStatus.INTERNAL_SERVER_ERROR, + assertEquals("Expected the response to be 404", HttpStatus.NOT_FOUND, responseEntity.getStatusCode()); } diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/QueryConsumerTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/QueryConsumerTest.java index 80efe37..b894985 100644 --- a/aai-traversal/src/test/java/org/onap/aai/rest/QueryConsumerTest.java +++ b/aai-traversal/src/test/java/org/onap/aai/rest/QueryConsumerTest.java @@ -96,7 +96,7 @@ public class QueryConsumerTest { headers.add("X-TransactionId", "JUNIT"); String authorization = Base64.getEncoder().encodeToString("AAI:AAI".getBytes("UTF-8")); headers.add("Authorization", "Basic " + authorization); - baseUrl = "https://localhost:" + randomPort; + baseUrl = "http://localhost:" + randomPort; httpTestUtil = new HttpTestUtil(); addPserver(); diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/dsl/DslQueryProcessorTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/dsl/DslQueryProcessorTest.java index e6665fd..340f8f8 100644 --- a/aai-traversal/src/test/java/org/onap/aai/rest/dsl/DslQueryProcessorTest.java +++ b/aai-traversal/src/test/java/org/onap/aai/rest/dsl/DslQueryProcessorTest.java @@ -19,20 +19,77 @@ */ package org.onap.aai.rest.dsl; -import static org.junit.Assert.assertEquals; - -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; - import org.onap.aai.AAISetup; import org.onap.aai.exceptions.AAIException; +import static org.junit.Assert.assertEquals; + /** * The Class DslMain. */ public class DslQueryProcessorTest extends AAISetup { + @Rule + public ExpectedException expectedEx = ExpectedException.none(); + + @Test + public void singleNode1() throws AAIException { + String aaiQuery = "cloud-region* !('cloud-owner','coid')"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesExcludeByProperty('cloud-owner','coid')" + + ".store('x').cap('x').unfold().dedup()"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void singleNodeLimit() throws AAIException { + String aaiQuery = "cloud-region* !('cloud-owner','coid') LIMIT 10"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesExcludeByProperty('cloud-owner','coid')" + + ".store('x').cap('x').unfold().dedup().limit(10)"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void specialCharacterTest() throws AAIException { + String aaiQuery = "cloud-region* !('cloud-owner','coidhello:?_-)(!@#$%^&*+={}[]|/.<,') LIMIT 10"; + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesExcludeByProperty('cloud-owner','coidhello:?_-)(!@#$%^&*+={}[]|/.<,')" + + ".store('x').cap('x').unfold().dedup().limit(10)"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void singleNodeLimitBlah() throws AAIException { + String aaiQuery = "cloud-region* !('cloud-owner','coid') LIMIT blah"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesExcludeByProperty('cloud-owner','coid')" + + ".getVerticesByProperty('cloud-region-id','cr id').store('x').cap('x').unfold().dedup().limit(10)"; + + expectedEx.expect(org.onap.aai.exceptions.AAIException.class); + expectedEx.expectMessage("DSL Syntax Error while processing the query"); + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + } + + @Test + public void singleNodeLimitNull() throws AAIException { + String aaiQuery = "cloud-region* !('cloud-owner','coid') LIMIT "; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesExcludeByProperty('cloud-owner','coid')" + + ".getVerticesByProperty('cloud-region-id','cr id').store('x').cap('x').unfold().dedup().limit(10)"; + + expectedEx.expect(org.onap.aai.exceptions.AAIException.class); + expectedEx.expectMessage("DSL Syntax Error while processing the query"); + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + } @Test public void cloudRegion1Test() throws AAIException { @@ -48,10 +105,14 @@ public class DslQueryProcessorTest extends AAISetup { @Test public void cloudRegion_entitlementTest() throws AAIException { - String aaiQuery = "generic-vnf('vnf-id','vnfId') (> vserver > tenant > cloud-region*('cloud-region-id','One')) > entitlement*"; + /* + A store within a where makes no sense + */ + String aaiQuery = "generic-vnf('vnf-id','vnfId') ( > vserver > tenant > cloud-region('cloud-region-id','One')) > entitlement*"; + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'generic-vnf').getVerticesByProperty('vnf-id','vnfId').where(" + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','vserver').createEdgeTraversal(EdgeType.TREE, 'vserver','tenant').createEdgeTraversal(EdgeType.TREE, 'tenant','cloud-region')" - + ".getVerticesByProperty('cloud-region-id','One').store('x'))" + + ".getVerticesByProperty('cloud-region-id','One'))" + ".createEdgeTraversal(EdgeType.TREE, 'generic-vnf','entitlement').store('x').cap('x').unfold().dedup()"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); @@ -59,9 +120,23 @@ public class DslQueryProcessorTest extends AAISetup { } @Test + public void cloudRegion_entitlementTestWithLabels() throws AAIException { + + String aaiQuery = "generic-vnf('vnf-id','vnfId') (> ('tosca.relationships.HostedOn') vserver > ('org.onap.relationships.inventory.BelongsTo') tenant > ('org.onap.relationships.inventory.BelongsTo') cloud-region('cloud-region-id','One')) > ('org.onap.relationships.inventory.ComposedOf')service-instance*"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'generic-vnf').getVerticesByProperty('vnf-id','vnfId').where(" + + "builder.newInstance().createEdgeTraversalWithLabels( 'generic-vnf','vserver', new ArrayList<>(Arrays.asList('tosca.relationships.HostedOn'))).createEdgeTraversalWithLabels( 'vserver','tenant', new ArrayList<>(Arrays.asList('org.onap.relationships.inventory.BelongsTo'))).createEdgeTraversalWithLabels( 'tenant','cloud-region', new ArrayList<>(Arrays.asList('org.onap.relationships.inventory.BelongsTo')))" + + ".getVerticesByProperty('cloud-region-id','One'))" + + ".createEdgeTraversalWithLabels( 'generic-vnf','service-instance', new ArrayList<>(Arrays.asList('org.onap.relationships.inventory.ComposedOf'))).store('x').cap('x').unfold().dedup()"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test public void complex_az_fromComplexTest() throws AAIException { - String aaiQuery = "cloud-region('cloud-owner','coid')('cloud-region-id','crid') > [ availability-zone* , complex*]"; + String aaiQuery = "cloud-region('cloud-owner','coid')('cloud-region-id','crid') > [ availability-zone* , complex*]"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region')" + ".getVerticesByProperty('cloud-owner','coid').getVerticesByProperty('cloud-region-id','crid')" @@ -72,6 +147,19 @@ public class DslQueryProcessorTest extends AAISetup { } @Test + public void complex_az_fromComplexTestWithLabels() throws AAIException { + + String aaiQuery = "cloud-region('cloud-owner','coid')('cloud-region-id','crid') > [ ('org.onap.relationships.inventory.BelongsTo')availability-zone* , ('org.onap.relationships.inventory.LocatedIn')complex*]"; + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region')" + + ".getVerticesByProperty('cloud-owner','coid').getVerticesByProperty('cloud-region-id','crid')" + + ".union(builder.newInstance().createEdgeTraversalWithLabels( 'cloud-region','availability-zone', new ArrayList<>(Arrays.asList('org.onap.relationships.inventory.BelongsTo'))).store('x')" + + ",builder.newInstance().createEdgeTraversalWithLabels( 'cloud-region','complex', new ArrayList<>(Arrays.asList('org.onap.relationships.inventory.LocatedIn'))).store('x')).cap('x').unfold().dedup()"; + + assertEquals(dslQuery, query); + } + + @Test public void cloudRegion_fromComplex1Test() throws AAIException { String builderQuery = "builder.getVerticesByProperty('aai-node-type', 'complex').getVerticesByProperty('data-center-code','data-center-code-name')" @@ -102,8 +190,8 @@ public class DslQueryProcessorTest extends AAISetup { + ".where(builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'vserver','generic-vnf').getVerticesByProperty('vnf-name','ZALL1MMSC03'))" + ".createEdgeTraversal(EdgeType.TREE, 'vserver','tenant').createEdgeTraversal(EdgeType.TREE, 'tenant','cloud-region')" + ".store('x').cap('x').unfold().dedup()"; - String aaiQuery = "image('application-vendor','F5') > vserver (>generic-vnf('vnf-name','ZALL1MMSC03')) > tenant > cloud-region*"; + String aaiQuery = "image('application-vendor','F5') > vserver (> generic-vnf('vnf-name','ZALL1MMSC03')) > tenant > cloud-region*"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); assertEquals(builderQuery, query); } @@ -117,8 +205,7 @@ public class DslQueryProcessorTest extends AAISetup { + ").createEdgeTraversal(EdgeType.TREE, 'vserver','tenant').createEdgeTraversal(EdgeType.TREE, 'tenant','cloud-region')" + ".store('x').cap('x').unfold().dedup()"; - String aaiQuery = "image('application-vendor','vendor') > vserver( >generic-vnf('nf-type', 'nfType') ) > tenant > cloud-region*"; - + String aaiQuery = "image('application-vendor','vendor') > vserver(> generic-vnf('nf-type', 'nfType') ) > tenant > cloud-region*"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); assertEquals(builderQuery, query); @@ -166,8 +253,8 @@ public class DslQueryProcessorTest extends AAISetup { + ".createEdgeTraversal(EdgeType.COUSIN, 'pserver','complex').store('x')" + ").cap('x').unfold().dedup()"; - String aaiQuery = "generic-vnf*('vnf-id','vnfId') > " + "[ pserver* > complex*, " - + " vserver > pserver* > complex* " + "]"; + String aaiQuery = "generic-vnf*('vnf-id','vnfId') > [ pserver* > complex*, " + + " vserver > pserver* > complex* " + "]"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); @@ -175,19 +262,17 @@ public class DslQueryProcessorTest extends AAISetup { } @Test - public void complex_fromVnfTest() throws AAIException { + public void complex_fromVnfTest2() throws AAIException { String builderQuery = "builder.getVerticesByProperty('aai-node-type', 'generic-vnf').getVerticesByProperty('vnf-id','vnfId').store('x').union(" - + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','pserver').store('x')" - + ".createEdgeTraversal(EdgeType.COUSIN, 'pserver','complex').store('x')," + + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','pserver').store('x')," + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','vserver')" - + ".createEdgeTraversal(EdgeType.COUSIN, 'vserver','pserver').store('x')" + + ".createEdgeTraversal(EdgeType.COUSIN, 'vserver','pserver').store('x'))" + ".createEdgeTraversal(EdgeType.COUSIN, 'pserver','complex').store('x')" - + ").cap('x').unfold().dedup()"; - - String aaiQuery = "generic-vnf*('vnf-id','vnfId') > " + "[ pserver* > complex*, " - + " vserver > pserver* > complex* " + "]"; + + ".cap('x').unfold().dedup()"; + String aaiQuery = "generic-vnf*('vnf-id','vnfId') > [ pserver* , " + + " vserver > pserver* ] > complex*"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); assertEquals(builderQuery, query); @@ -208,8 +293,7 @@ public class DslQueryProcessorTest extends AAISetup { String aaiQuery = "customer('global-customer-id', 'a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb') > service-subscription('service-subscription-id', 'Nimbus') " + " > service-instance('service-instance-id','sid') > generic-vnf* " - + " > [ vnfc* , vserver*, pserver* , pnf* ]"; - + + " > [ vnfc* , vserver*, pserver* , pnf* ]"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); assertEquals(builderQuery, query); @@ -222,8 +306,8 @@ public class DslQueryProcessorTest extends AAISetup { + ".getVerticesByProperty('hostname','hostname1'),builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','vserver')" + ".createEdgeTraversal(EdgeType.COUSIN, 'vserver','pserver').getVerticesByProperty('hostname','hostname1'))).store('x').cap('x').unfold().dedup()"; - String aaiQuery = "generic-vnf*('vnf-id','vnfId') (> [pserver('hostname','hostname1'), " - + "vserver > pserver('hostname','hostname1')])"; + String aaiQuery = "generic-vnf*('vnf-id','vnfId') (> [ pserver('hostname','hostname1'), " + + " vserver > pserver('hostname','hostname1')])"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); assertEquals(builderQuery, query); @@ -259,7 +343,7 @@ public class DslQueryProcessorTest extends AAISetup { @Test public void hasNotPropertyNullValuesTest() throws AAIException { String aaiQuery = "cloud-region* !('cloud-owner',' ',' null ')"; - String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesExcludeByProperty('cloud-owner', new ArrayList<>(Arrays.asList('','null'))).store('x').cap('x').unfold().dedup()"; + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesExcludeByProperty('cloud-owner', new ArrayList<>(Arrays.asList(' ',' null '))).store('x').cap('x').unfold().dedup()"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); assertEquals(dslQuery, query); @@ -267,12 +351,38 @@ public class DslQueryProcessorTest extends AAISetup { @Test public void hasPropertyIntegerTest() throws AAIException { - String aaiQuery = "cloud-region('cloud-owner', 'att-nc')('cloud-region-id', 'MTN61a') > vlan-range > vlan-tag*('vlan-id-inner', 20)"; - String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesByProperty('cloud-owner','att-nc').getVerticesByProperty('cloud-region-id','MTN61a').getVerticesByProperty('vlan-id-inner',20).store('x').cap('x').unfold().dedup()"; + String aaiQuery = "cloud-region('cloud-owner', 'att-nc')('cloud-region-id', 'MTN61a') > vlan-tag*('vlan-id-inner', 20)"; + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesByProperty('cloud-owner','att-nc').getVerticesByProperty('cloud-region-id','MTN61a').createEdgeTraversal(EdgeType.COUSIN, 'cloud-region','vlan-tag').getVerticesByProperty('vlan-id-inner',20).store('x').cap('x').unfold().dedup()"; + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void noEdgeRuleTest() throws AAIException { + String aaiQuery = "vserver('vserver-id','abc') > logical-link* > l-interface*"; + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'vserver').getVerticesByProperty('vserver-id','abc').createEdgeTraversal(EdgeType.TREE, 'vserver','logical-link').store('x').createEdgeTraversal('logical-link','l-interface').store('x')cap('x').unfold().dedup()"; + expectedEx.expect(org.onap.aai.exceptions.AAIException.class); + expectedEx.expectMessage("No EdgeRule found for passed nodeTypes: vserver, logical-link"); + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void multipleEdgeRuleTest() throws AAIException { + String aaiQuery = "vserver('vserver-id','abc') > l-interface* > lag-interface*"; + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'vserver').getVerticesByProperty('vserver-id','abc').createEdgeTraversal(EdgeType.TREE, 'vserver','l-interface').store('x').createEdgeTraversal( 'l-interface','lag-interface').store('x').cap('x').unfold().dedup()"; + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void multipleEdgeRuleTestWithLabels() throws AAIException { + String aaiQuery = "vserver('vserver-id','abc') > l-interface* > ('org.onap.relationships.inventory.BelongsTo') lag-interface*"; + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'vserver').getVerticesByProperty('vserver-id','abc').createEdgeTraversal(EdgeType.TREE, 'vserver','l-interface').store('x').createEdgeTraversalWithLabels( 'l-interface','lag-interface', new ArrayList<>(Arrays.asList('org.onap.relationships.inventory.BelongsTo'))).store('x').cap('x').unfold().dedup()"; String query = dslQueryProcessor.parseAaiQuery(aaiQuery); assertEquals(dslQuery, query); } - + @Test public void hasNotPropertyTest() throws AAIException { String aaiQuery = "cloud-region* !('cloud-owner')"; @@ -282,4 +392,63 @@ public class DslQueryProcessorTest extends AAISetup { assertEquals(dslQuery, query); } + @Test + public void overlyNestedQueryTest() throws AAIException { + String aaiQuery = "generic-vnf*('vnf-id','vnfId') (> [ pserver('hostname','hostname1'), vserver (> [ pserver('hostname','hostname1'), pserver('hostname','hostname1')])]) > vserver"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'generic-vnf').getVerticesByProperty('vnf-id','vnfId').where(builder.newInstance().union" + + "(builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','pserver').getVerticesByProperty('hostname','hostname1')," + + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','vserver').where(builder.newInstance().union(builder.newInstance()" + + ".createEdgeTraversal(EdgeType.COUSIN, 'vserver','pserver').getVerticesByProperty('hostname','hostname1'),builder.newInstance()." + + "createEdgeTraversal(EdgeType.COUSIN, 'vserver','pserver').getVerticesByProperty('hostname','hostname1'))))).store('x').createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','vserver').cap('x').unfold().dedup()"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void overlyNestedQueryTestWithLabels() throws AAIException { + String aaiQuery = "generic-vnf*('vnf-id','vnfId') (> [ ('tosca.relationships.HostedOn')pserver('hostname','hostname1'), ('tosca.relationships.HostedOn')vserver (> [ ('tosca.relationships.HostedOn')pserver('hostname','hostname1'), ('tosca.relationships.HostedOn')pserver('hostname','hostname1')])]) > ('org.onap.relationships.inventory.PartOf')allotted-resource"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'generic-vnf').getVerticesByProperty('vnf-id','vnfId').where(builder.newInstance().union" + + "(builder.newInstance().createEdgeTraversalWithLabels( 'generic-vnf','pserver', new ArrayList<>(Arrays.asList('tosca.relationships.HostedOn'))).getVerticesByProperty('hostname','hostname1')," + + "builder.newInstance().createEdgeTraversalWithLabels( 'generic-vnf','vserver', new ArrayList<>(Arrays.asList('tosca.relationships.HostedOn'))).where(builder.newInstance().union(builder.newInstance()" + + ".createEdgeTraversalWithLabels( 'vserver','pserver', new ArrayList<>(Arrays.asList('tosca.relationships.HostedOn'))).getVerticesByProperty('hostname','hostname1'),builder.newInstance()." + + "createEdgeTraversalWithLabels( 'vserver','pserver', new ArrayList<>(Arrays.asList('tosca.relationships.HostedOn'))).getVerticesByProperty('hostname','hostname1'))))).store('x').createEdgeTraversalWithLabels( 'generic-vnf','allotted-resource', new ArrayList<>(Arrays.asList('org.onap.relationships.inventory.PartOf'))).cap('x').unfold().dedup()"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void nestedUnionQueryTest() throws AAIException { + + String builderQuery = "builder.getVerticesByProperty('aai-node-type', 'generic-vnf').getVerticesByProperty('vnf-id','vnfId').store('x').union(" + + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','pserver').store('x')," + + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','vserver')" + + ".createEdgeTraversal(EdgeType.COUSIN, 'vserver','pserver').store('x'))" + + ".createEdgeTraversal(EdgeType.COUSIN, 'pserver','complex').store('x')" + + ".union(builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'complex','availability-zone')" + + ".createEdgeTraversal(EdgeType.TREE, 'availability-zone','cloud-region').store('x')," + + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'complex','cloud-region').store('x')," + + "builder.newInstance().createEdgeTraversal(EdgeType.TREE, 'complex','ctag-pool').store('x').union(" + + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'ctag-pool','availability-zone').store('x')" + + ".createEdgeTraversal(EdgeType.COUSIN, 'availability-zone','complex').store('x')," + + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'ctag-pool','generic-vnf').store('x')" + + ".createEdgeTraversal(EdgeType.COUSIN, 'generic-vnf','availability-zone').store('x')" + + ".createEdgeTraversal(EdgeType.COUSIN, 'availability-zone','complex').store('x')," + + "builder.newInstance().createEdgeTraversal(EdgeType.COUSIN, 'ctag-pool','vpls-pe').store('x')" + + ".createEdgeTraversal(EdgeType.COUSIN, 'vpls-pe','complex').store('x'))" + + ".createEdgeTraversal(EdgeType.COUSIN, 'complex','cloud-region').store('x'))" + + ".createEdgeTraversal(EdgeType.TREE, 'cloud-region','tenant').store('x')" + + ".cap('x').unfold().dedup()"; + + String aaiQuery = "generic-vnf*('vnf-id','vnfId') > [ pserver* , " + + " vserver > pserver* ] > complex* > [ availability-zone > cloud-region*, cloud-region*, " + + " ctag-pool* > [ availability-zone* > complex* , generic-vnf* > availability-zone* > complex*, vpls-pe* > complex*] > cloud-region*] > tenant* " ; + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + + assertEquals(builderQuery, query); + } + } diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/dsl/ProdDslTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/dsl/ProdDslTest.java new file mode 100644 index 0000000..822643e --- /dev/null +++ b/aai-traversal/src/test/java/org/onap/aai/rest/dsl/ProdDslTest.java @@ -0,0 +1,95 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.rest.dsl; + +import org.junit.Test; +import org.onap.aai.AAISetup; +import org.onap.aai.exceptions.AAIException; + +import static org.junit.Assert.assertEquals; + +//TODO: Change this to read queries and their builder equivalent from a file +//TODO: Add queries run by SEs + +public class ProdDslTest extends AAISetup { + @Test + public void msoQueryTest1() throws AAIException { + String aaiQuery = "cloud-region('cloud-owner', 'value')('cloud-region-id', 'value') > vlan-tag*('vlan-id-outer', 'value')"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'cloud-region').getVerticesByProperty('cloud-owner','value')" + + ".getVerticesByProperty('cloud-region-id','value').createEdgeTraversal(EdgeType.COUSIN, 'cloud-region','vlan-tag')" + + ".getVerticesByProperty('vlan-id-outer','value').store('x').cap('x').unfold().dedup()"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void msoQueryTest2() throws AAIException { + String aaiQuery = "pserver('hostname', 'pserver-1') > p-interface > sriov-pf*('pf-pci-id', '0000:ee:00.0')"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'pserver').getVerticesByProperty('hostname','pserver-1')" + + ".createEdgeTraversal(EdgeType.TREE, 'pserver','p-interface')" + + ".createEdgeTraversal(EdgeType.TREE, 'p-interface','sriov-pf').getVerticesByProperty('pf-pci-id','0000:ee:00.0').store('x').cap('x').unfold().dedup()"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + @Test + public void msoQueryTest3() throws AAIException { + String aaiQuery = "l-interface ('interface-id', 'value') > sriov-vf > sriov-pf*"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'l-interface').getVerticesByProperty('interface-id','value')" + + ".createEdgeTraversal(EdgeType.TREE, 'l-interface','sriov-vf')" + + ".createEdgeTraversal(EdgeType.COUSIN, 'sriov-vf','sriov-pf').store('x').cap('x').unfold().dedup()"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + //TODO : Get this from schema + @Test + public void msoQueryTest4() throws AAIException { + //String aaiQuery = "l-interface ('interface-id', 'value') > lag-interface('interface-name', 'bond1') > sriov-pf*"; + String aaiQuery = "l-interface ('interface-id', 'value') > lag-interface('interface-name', 'bond1') > p-interface > sriov-pf*"; + + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'l-interface').getVerticesByProperty('interface-id','value')" + + ".createEdgeTraversal( 'l-interface','lag-interface').getVerticesByProperty('interface-name','bond1')" + + ".createEdgeTraversal(EdgeType.COUSIN, 'lag-interface','p-interface').createEdgeTraversal(EdgeType.TREE, 'p-interface','sriov-pf').store('x').cap('x').unfold().dedup()"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + + //TODO : Get this from schema + @Test + public void msoQueryTest5() throws AAIException { + //String aaiQuery = "pserver ('hostname', 'value') > vserver ('vserver-name', 'value') > l-interface > vlan-tag*"; + String aaiQuery = "pserver ('hostname', 'value') > vserver ('vserver-name', 'value') > l-interface > cp > vlan-tag*"; + String dslQuery = "builder.getVerticesByProperty('aai-node-type', 'pserver').getVerticesByProperty('hostname','value')" + + ".createEdgeTraversal(EdgeType.COUSIN, 'pserver','vserver').getVerticesByProperty('vserver-name','value')" + + ".createEdgeTraversal(EdgeType.TREE, 'vserver','l-interface').createEdgeTraversal(EdgeType.COUSIN, 'l-interface','cp').createEdgeTraversal(EdgeType.COUSIN, 'cp','vlan-tag').store('x').cap('x').unfold().dedup()"; + + String query = dslQueryProcessor.parseAaiQuery(aaiQuery); + assertEquals(dslQuery, query); + } + +}
\ No newline at end of file diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/search/GetVNFVpnBondingServiceDetailsTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/search/GetVNFVpnBondingServiceDetailsTest.java new file mode 100644 index 0000000..b859b84 --- /dev/null +++ b/aai-traversal/src/test/java/org/onap/aai/rest/search/GetVNFVpnBondingServiceDetailsTest.java @@ -0,0 +1,112 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.rest.search; + +import java.util.Map; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.junit.Ignore; +import org.junit.Test; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException; + +public class GetVNFVpnBondingServiceDetailsTest extends QueryTest { + + public GetVNFVpnBondingServiceDetailsTest() throws AAIException, NoEdgeRuleFoundException { + super(); + } + + // Test ignored for time being as query files pulled from aai-queries in schema-service differ + // from the stored-queries.json file that used to reside in traversal. + @Ignore + @Test + public void run() { + super.run(); + } + + @Override + protected void createGraph() throws AAIException, NoEdgeRuleFoundException { + //Set up the test graph + + + Vertex gnvf1 = graph.addVertex(T.label, "generic-vnf", T.id, "0", "aai-node-type", "generic-vnf", "vnf-id", "vnf-id-1", "vnf-name", "vnf-name-1"); + Vertex vserver = graph.addVertex(T.label, "vserver", T.id, "1", "aai-node-type", "vserver", "vserver-name1", "vservername1"); + Vertex linter1 = graph.addVertex(T.label, "l-interface", T.id, "2", "aai-node-type", "l-interface", "l-interface-id", "l-interface-id-1", "l-interface-name", "l-interface-name1"); + Vertex linter2 = graph.addVertex(T.label, "l-interface", T.id, "3", "aai-node-type", "l-interface", "l-interface-id", "l-interface-id-2", "l-interface-name", "l-interface-name2"); + Vertex vlan1 = graph.addVertex(T.label, "vlan", T.id, "4", "aai-node-type", "vlan","vlan-interface", "vlan11"); + Vertex config1 = graph.addVertex(T.label, "configuration", T.id, "5", "aai-node-type", "configuration", "configuration-id", "configuration1"); + Vertex l3network1 = graph.addVertex(T.label, "l3-network", T.id, "6", "aai-node-type", "l3-network", "ll3-network-id", "l3-network-id-1", "l3-network-name", "l3-network-name1"); + Vertex l3inter1ipv4addresslist = graph.addVertex(T.label, "interface-ipv4-address-list", T.id, "7", "aai-node-type", "l3-interface-ipv4-address-list", "l3-interface-ipv4-address-list-id", "l3-interface-ipv4-address-list-id-1", "l3-interface-ipv6-address-list-name", "l3-interface-ipv6-address-list-name1"); + Vertex l3inter1ipv6addresslist = graph.addVertex(T.label, "l3-interface-ipv6-address-list", T.id, "8", "aai-node-type", "l3-interface-ipv6-address-list", "l3-interface-ipv6-address-list-id", "l3-interface-ipv6-address-list-id-1", "l3-interface-ipv6-address-list-name", "l3-interface-ipv6-address-list-name1"); + Vertex configVpnBinding = graph.addVertex(T.label, "vpn-binding", T.id, "9", "aai-node-type", "vpn-binding", + "vpn-id", "test-binding-config", "vpn-name", "test"); + Vertex customer = graph.addVertex(T.label, "customer", T.id, "10", "aai-node-type", "customer", "customer-id", "customer-id-1", "customer-name", "customer-name1"); + Vertex subnet1 = graph.addVertex(T.label, "subnet", T.id, "11", "aai-node-type", "subnet", "subnet-id", "subnet-id-11"); + Vertex routeTarget1 = graph.addVertex(T.label, "route-target", T.id, "12", "aai-node-type", "route-target", "global-route-target", "111"); + + + GraphTraversalSource g = graph.traversal(); + rules.addEdge(g, gnvf1, vserver);//false + rules.addEdge(g, gnvf1, config1);//false + rules.addTreeEdge(g, vserver, linter1);//true + rules.addTreeEdge(g, linter1, linter2);//true + rules.addTreeEdge(g, linter2, vlan1);//true + rules.addEdge(g, config1, l3network1 );//false + rules.addTreeEdge(g, l3network1, subnet1);//true + rules.addEdge(g, subnet1, l3inter1ipv4addresslist );//false + rules.addEdge(g, subnet1, l3inter1ipv6addresslist );//false + rules.addEdge(g, l3network1, configVpnBinding );//false + rules.addEdge(g, configVpnBinding, customer );//false + rules.addTreeEdge(g, configVpnBinding, routeTarget1);//true + + + expectedResult.add(vserver); + expectedResult.add(config1); + expectedResult.add(linter1); + expectedResult.add(linter2); + expectedResult.add(vlan1); + expectedResult.add(l3network1); + expectedResult.add(subnet1); + expectedResult.add(l3inter1ipv4addresslist); + expectedResult.add(l3inter1ipv6addresslist); + expectedResult.add(configVpnBinding); + expectedResult.add(customer); + expectedResult.add(routeTarget1); + + } + + @Override + protected String getQueryName() { + return "getVNFVpnBondingServiceDetails"; + } + @Override + protected void addStartNode(GraphTraversal<Vertex, Vertex> g) { + g.has("vnf-name", "vnf-name-1"); + + } + @Override + protected void addParam(Map<String, Object> params) { + params.put("vnf-name", "vnf-name-1"); + } +} diff --git a/aai-traversal/src/test/resources/application-onap-test.properties b/aai-traversal/src/test/resources/application-onap-test.properties index fc53f7a..48a0b60 100644 --- a/aai-traversal/src/test/resources/application-onap-test.properties +++ b/aai-traversal/src/test/resources/application-onap-test.properties @@ -57,7 +57,7 @@ schema.ingest.file=${server.local.startpath}/application-test.properties # Schema Version Related Attributes schema.uri.base.path=/aai # Lists all of the versions in the schema -schema.version.list=v10,v11,v12,v13,v14,v15 +schema.version.list=v10,v11,v12,v13,v14,v15,v16 # Specifies from which version should the depth parameter to default to zero schema.version.depth.start=v10 # Specifies from which version should the related link be displayed in response payload @@ -70,5 +70,5 @@ schema.version.namespace.change.start=v12 # Specifies from which version should the client start seeing the edge label in payload schema.version.edge.label.start=v12 # Specifies the version that the application should default to -schema.version.api.default=v15 +schema.version.api.default=v16 schema.translator.list=config
\ No newline at end of file diff --git a/aai-traversal/src/test/resources/application-test.properties b/aai-traversal/src/test/resources/application-test.properties index 57b51d5..7e244bb 100644 --- a/aai-traversal/src/test/resources/application-test.properties +++ b/aai-traversal/src/test/resources/application-test.properties @@ -12,7 +12,7 @@ spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSou spring.jersey.application-path=${schema.uri.base.path} -spring.profiles.active=production,one-way-ssl +spring.profiles.active=production #The max number of active threads in this pool server.tomcat.max-threads=200 #The minimum number of threads always kept alive @@ -29,13 +29,14 @@ server.local.startpath=src/main/resources/ server.basic.auth.location=${server.local.startpath}etc/auth/realm.properties server.port=8446 -server.ssl.enabled-protocols=TLSv1.1,TLSv1.2 -server.ssl.key-store=${server.local.startpath}etc/auth/aai_keystore -server.ssl.key-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0) -server.ssl.trust-store=${server.local.startpath}etc/auth/aai_keystore -server.ssl.trust-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0) -server.ssl.client-auth=want -server.ssl.key-store-type=JKS +security.require-ssl=false +server.ssl.enabled=false +#server.ssl.enabled-protocols=TLSv1.1,TLSv1.2 +#server.ssl.key-store=${server.local.startpath}etc/auth/aai_keystore +#server.ssl.key-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0) +#server.ssl.trust-store-password=password(OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0) +#server.ssl.client-auth=want +#server.ssl.key-store-type=JKS # JMS bind address host port jms.bind.address=tcp://localhost:61646 @@ -60,7 +61,7 @@ schema.ingest.file=${server.local.startpath}/application-test.properties # Schema Version Related Attributes schema.uri.base.path=/aai # Lists all of the versions in the schema -schema.version.list=v10,v11,v12,v13,v14,v15 +schema.version.list=v10,v11,v12,v13,v14,v15,v16 # Specifies from which version should the depth parameter to default to zero schema.version.depth.start=v10 # Specifies from which version should the related link be displayed in response payload @@ -73,6 +74,6 @@ schema.version.namespace.change.start=v12 # Specifies from which version should the client start seeing the edge label in payload schema.version.edge.label.start=v12 # Specifies the version that the application should default to -schema.version.api.default=v15 +schema.version.api.default=v16 schema.translator.list=config diff --git a/aai-traversal/src/test/resources/schema-ingest.properties b/aai-traversal/src/test/resources/schema-ingest.properties index f461aea..9371645 100644 --- a/aai-traversal/src/test/resources/schema-ingest.properties +++ b/aai-traversal/src/test/resources/schema-ingest.properties @@ -2,9 +2,9 @@ schema.configuration.location=N/A schema.nodes.location=src/main/resources/etc/oxm/ schema.edges.location=src/main/resources/etc/dbedgerules/ -schema.version.list=v10,v11,v12,v13,v14,v15 +schema.version.list=v10,v11,v12,v13,v14,v15,v16 schema.version.depth.start=v10 schema.version.related.link.start=v10 schema.version.app.root.start=v11 schema.version.edge.label.start=v12 -schema.version.api.default=v15 +schema.version.api.default=v16 |