From 16b48ab05e63fca707585b4ecee466b8b7721a1b Mon Sep 17 00:00:00 2001 From: "LaMont, William (wl2432)" Date: Fri, 11 Jan 2019 15:21:39 -0500 Subject: Update traversal to support v15 Issue-ID: AAI-2073 Change-Id: I1c3df218d1333bdebc984947edc100607958ab60 Signed-off-by: LaMont, William (wl2432) --- .../src/main/java/org/onap/aai/TraversalApp.java | 66 +++++++++++++++-- .../java/org/onap/aai/config/DslConfiguration.java | 6 +- .../org/onap/aai/config/SearchConfiguration.java | 26 ++++++- .../java/org/onap/aai/dbgraphmap/SearchGraph.java | 3 +- .../main/java/org/onap/aai/rest/DslConsumer.java | 42 ++++++++--- .../main/java/org/onap/aai/rest/QueryConsumer.java | 82 ++++++++++++++++++--- .../java/org/onap/aai/rest/RecentAPIConsumer.java | 17 ++++- .../java/org/onap/aai/rest/dsl/DslContext.java | 38 +++++++++- .../java/org/onap/aai/rest/dsl/DslListener.java | 46 +++++++++++- .../org/onap/aai/rest/dsl/DslQueryBuilder.java | 72 +++++++++++++++--- .../org/onap/aai/rest/dsl/DslQueryProcessor.java | 21 ++++-- .../java/org/onap/aai/rest/search/CQConfig.java | 28 +++++++ .../aai/rest/search/GenericQueryProcessor.java | 9 +-- .../aai/rest/search/GremlinServerSingleton.java | 47 ++---------- .../org/onap/aai/rest/search/GroovyShellImpl.java | 4 +- .../org/onap/aai/rest/search/LocalCQConfig.java | 85 ++++++++++++++++++++++ .../onap/aai/rest/search/NodeQueryProcessor.java | 6 +- .../aai/rest/search/SchemaServiceCQConfig.java | 64 ++++++++++++++++ .../java/org/onap/aai/util/TraversalConstants.java | 2 + 19 files changed, 557 insertions(+), 107 deletions(-) create mode 100644 aai-traversal/src/main/java/org/onap/aai/rest/search/CQConfig.java create mode 100644 aai-traversal/src/main/java/org/onap/aai/rest/search/LocalCQConfig.java create mode 100644 aai-traversal/src/main/java/org/onap/aai/rest/search/SchemaServiceCQConfig.java (limited to 'aai-traversal/src/main/java/org') 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 2797545..64a3b44 100644 --- a/aai-traversal/src/main/java/org/onap/aai/TraversalApp.java +++ b/aai-traversal/src/main/java/org/onap/aai/TraversalApp.java @@ -21,10 +21,12 @@ package org.onap.aai; import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.onap.aai.config.PropertyPasswordConfiguration; import org.onap.aai.config.SpringContextAware; import org.onap.aai.dbmap.AAIGraph; import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; import org.onap.aai.logging.LoggingContext; import org.onap.aai.logging.LoggingContext.StatusCode; import org.onap.aai.nodes.NodeIngestor; @@ -56,7 +58,8 @@ import java.util.Map; "org.onap.aai.setup", "org.onap.aai.tasks", "org.onap.aai.service", - "org.onap.aai.rest" + "org.onap.aai.rest", + "org.onap.aai.rest-client" }) @EnableAutoConfiguration(exclude = { @@ -122,14 +125,40 @@ public class TraversalApp { AAIGraph.getInstance().graphShutdown(); } - public static void main(String[] args) { + public static void main(String[] args) throws AAIException{ + + setDefaultProps(); + + LoggingContext.save(); + LoggingContext.component("init"); + LoggingContext.partnerName("NA"); + LoggingContext.targetEntity(APP_NAME); + LoggingContext.requestId(UUID.randomUUID().toString()); + LoggingContext.serviceName(APP_NAME); + LoggingContext.targetServiceName("contextInitialized"); + LoggingContext.statusCode(StatusCode.COMPLETE); + Environment env =null; + AAIConfig.init(); + + try{ + SpringApplication app = new SpringApplication(TraversalApp.class); + app.setLogStartupInfo(false); + app.setRegisterShutdownHook(true); + app.addInitializers(new PropertyPasswordConfiguration()); + env = app.run(args).getEnvironment(); + } + catch(Exception ex){ + AAIException aai = schemaServiceExceptionTranslator(ex); + LoggingContext.statusCode(LoggingContext.StatusCode.ERROR); + LoggingContext.responseCode(LoggingContext.DATA_ERROR); + logger.error("Problems starting Traversal "+aai.getMessage()); + ErrorLogHelper.logException(aai); + ErrorLogHelper.logError(aai.getCode(), ex.getMessage() + ", resolve and restart Traversal"); + //ErrorLogHelper.logError(aai.getCode(), aai.getMessage() + aai.getCause().toString()); + throw aai; + } + - setDefaultProps(); - SpringApplication app = new SpringApplication(TraversalApp.class); - app.setLogStartupInfo(false); - app.setRegisterShutdownHook(true); - app.addInitializers(new PropertyPasswordConfiguration()); - Environment env = app.run(args).getEnvironment(); MDC.setContextMap (contextMap); logger.info( "Application '{}' is running on {}!" , @@ -166,4 +195,25 @@ public class TraversalApp { } } + private static AAIException schemaServiceExceptionTranslator(Exception ex) { + AAIException aai = null; + logger.info("Error Message is "+ ExceptionUtils.getRootCause(ex).toString() + " details - "+ExceptionUtils.getRootCause(ex).getMessage()); + if(ExceptionUtils.getRootCause(ex).getMessage().contains("NodeIngestor")){ + aai = new AAIException("AAI_3026","Error reading OXM from SchemaService - Investigate"); + } + else if(ExceptionUtils.getRootCause(ex).getMessage().contains("EdgeIngestor")){ + aai = new AAIException("AAI_3027","Error reading EdgeRules from SchemaService - Investigate"); + } + else if(ExceptionUtils.getRootCause(ex).getMessage().contains("stored-queries")){ + aai = new AAIException("AAI_3027","Error reading EdgeRules from SchemaService - Investigate"); + } + else if(ExceptionUtils.getRootCause(ex).getMessage().contains("Connection refused")){ + aai = new AAIException("AAI_3025","Error connecting to SchemaService - Investigate"); + } + else { + aai = new AAIException("AAI_3025","Error connecting to SchemaService - Please Investigate"); + } + + return aai; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/config/DslConfiguration.java b/aai-traversal/src/main/java/org/onap/aai/config/DslConfiguration.java index 74bc046..311dd99 100644 --- a/aai-traversal/src/main/java/org/onap/aai/config/DslConfiguration.java +++ b/aai-traversal/src/main/java/org/onap/aai/config/DslConfiguration.java @@ -20,8 +20,10 @@ package org.onap.aai.config; import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.rest.dsl.DslListener; import org.onap.aai.rest.dsl.DslQueryProcessor; +import org.onap.aai.setup.SchemaVersions; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -32,8 +34,8 @@ public class DslConfiguration { @Bean @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public DslListener dslListener(EdgeIngestor edgeIngestor){ - return new DslListener(edgeIngestor); + public DslListener dslListener(EdgeIngestor edgeIngestor, SchemaVersions schemaVersions, LoaderFactory loaderFactory){ + return new DslListener(edgeIngestor, schemaVersions, loaderFactory); } @Bean diff --git a/aai-traversal/src/main/java/org/onap/aai/config/SearchConfiguration.java b/aai-traversal/src/main/java/org/onap/aai/config/SearchConfiguration.java index bef10d0..0b8238b 100644 --- a/aai-traversal/src/main/java/org/onap/aai/config/SearchConfiguration.java +++ b/aai-traversal/src/main/java/org/onap/aai/config/SearchConfiguration.java @@ -25,17 +25,30 @@ import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.rest.dsl.DslListener; import org.onap.aai.rest.dsl.DslQueryProcessor; +import org.onap.aai.rest.search.CQConfig; import org.onap.aai.rest.search.GremlinServerSingleton; +import org.onap.aai.rest.search.LocalCQConfig; +import org.onap.aai.rest.search.SchemaServiceCQConfig; import org.onap.aai.setup.SchemaVersions; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.Scope; @Configuration +@PropertySource(value = "classpath:schema-ingest.properties", ignoreResourceNotFound = true) +@PropertySource(value = "file:${schema.ingest.file}", ignoreResourceNotFound = true) + public class SearchConfiguration { + private static final String CONFIG_TRANSLATOR = "config"; + private static final String SCHEMA_SERVICE_TRANSLATOR = "schema-service"; + + @Value("${schema.translator.list}") + private String translator; + @Bean public SearchGraph searchGraph(LoaderFactory loaderFactory, EdgeIngestor edgeIngestor, SchemaVersions schemaVersions) { SearchGraph searchGraph = new SearchGraph(loaderFactory, edgeIngestor, schemaVersions); @@ -44,7 +57,18 @@ public class SearchConfiguration { @Bean public GremlinServerSingleton gremlinServerSingleton(){ - return new GremlinServerSingleton(); + return new GremlinServerSingleton(getCustomQueryConfig()); } + + @Bean + public CQConfig getCustomQueryConfig(){ + if(translator.equals(SCHEMA_SERVICE_TRANSLATOR)) { + return new SchemaServiceCQConfig(); + } + return new LocalCQConfig(); + } + + + } diff --git a/aai-traversal/src/main/java/org/onap/aai/dbgraphmap/SearchGraph.java b/aai-traversal/src/main/java/org/onap/aai/dbgraphmap/SearchGraph.java index 0725802..0221d8a 100644 --- a/aai-traversal/src/main/java/org/onap/aai/dbgraphmap/SearchGraph.java +++ b/aai-traversal/src/main/java/org/onap/aai/dbgraphmap/SearchGraph.java @@ -28,6 +28,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import java.util.stream.Stream; import javax.ws.rs.core.HttpHeaders; @@ -520,7 +521,7 @@ public class SearchGraph { edgeRules = edgeIngestor.getRules(query); //Map rules = EdgeRules.getInstance().getEdgeRules(targetNodeType, nodeType); - String[] results = edgeRules.keySet().toArray(new String[0]); + String[] results = edgeRules.values().stream().map(rule -> rule.getLabel()).collect(Collectors.toList()).toArray(new String[0]); return results; } 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 bdca63b..ad5fffb 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 @@ -59,6 +59,7 @@ import org.onap.aai.serialization.queryformats.Formatter; import org.onap.aai.serialization.queryformats.SubGraphStyle; import org.onap.aai.setup.SchemaVersion; import org.onap.aai.setup.SchemaVersions; +import org.onap.aai.util.AAIConfig; import org.onap.aai.util.TraversalConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -104,14 +105,14 @@ public class DslConsumer extends RESTAPI { public Response executeQuery(String content, @PathParam("version") String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("graphson") @QueryParam("format") String queryFormat, @DefaultValue("no_op") @QueryParam("subgraph") String subgraph, @Context HttpHeaders headers, - @Context UriInfo info, @Context HttpServletRequest req) { + @Context UriInfo info, @Context HttpServletRequest req, @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, @DefaultValue("-1") @QueryParam("resultSize") String resultSize) { return runner(TraversalConstants.AAI_TRAVERSAL_DSL_TIMEOUT_ENABLED, TraversalConstants.AAI_TRAVERSAL_DSL_TIMEOUT_APP, TraversalConstants.AAI_TRAVERSAL_DSL_TIMEOUT_LIMIT, headers, info, HttpMethod.PUT, new AaiCallable() { @Override public Response process() { return processExecuteQuery(content, versionParam, uri, queryFormat, subgraph, headers, info, - req); + req, resultIndex, resultSize); } }); } @@ -119,10 +120,11 @@ public class DslConsumer extends RESTAPI { public Response processExecuteQuery(String content, @PathParam("version") String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("graphson") @QueryParam("format") String queryFormat, @DefaultValue("no_op") @QueryParam("subgraph") String subgraph, @Context HttpHeaders headers, - @Context UriInfo info, @Context HttpServletRequest req) { + @Context UriInfo info, @Context HttpServletRequest req, @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, @DefaultValue("-1") @QueryParam("resultSize") String resultSize) { String methodName = "executeDslQuery"; String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String dslOverride = headers.getRequestHeaders().getFirst("X-DslOverride"); String realTime = headers.getRequestHeaders().getFirst("Real-Time"); Response response; SchemaVersion version = new SchemaVersion(versionParam); @@ -132,6 +134,7 @@ public class DslConsumer extends RESTAPI { LoggingContext.save(); DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime); traversalUriHttpEntry.setHttpEntryProperties(version, type); + traversalUriHttpEntry.setPaginationParameters(resultIndex, resultSize); dbEngine = traversalUriHttpEntry.getDbEngine(); JsonObject input = new JsonParser().parse(content).getAsJsonObject(); JsonElement dslElement = input.get("dsl"); @@ -145,29 +148,46 @@ public class DslConsumer extends RESTAPI { LoggingContext.startTime(); StopWatch.conditionalStart(); + boolean isDslOverride = dslOverride != null && !AAIConfig.get(TraversalConstants.DSL_OVERRIDE).equals("false") + && dslOverride.equals(AAIConfig.get(TraversalConstants.DSL_OVERRIDE)); + + if(isDslOverride) + dslQueryProcessor.setValidationFlag(false); + GenericQueryProcessor processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) .queryFrom(dsl, "dsl").queryProcessor(dslQueryProcessor).processWith(processorType).create(); - + String result = ""; SubGraphStyle subGraphStyle = SubGraphStyle.valueOf(subgraph); - List vertices = processor.execute(subGraphStyle); - + List vertTemp = processor.execute(subGraphStyle); + List vertices = traversalUriHttpEntry.getPaginatedVertexList(vertTemp); DBSerializer serializer = new DBSerializer(version, dbEngine, ModelType.MOXY, sourceOfTruth); Format format = Format.getFormat(queryFormat); FormatFactory ff = new FormatFactory(traversalUriHttpEntry.getLoader(), serializer, schemaVersions, this.basePath); - + Formatter formater = ff.get(format, info.getQueryParameters()); result = formater.output(vertices).toString(); - + double msecs = StopWatch.stopIfStarted(); LoggingContext.elapsedTime((long) msecs, TimeUnit.MILLISECONDS); LoggingContext.successStatusFields(); LOGGER.info("Completed"); - - response = Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(result).build(); - + + if(traversalUriHttpEntry.isPaginated()){ + response = Response.status(Status.OK) + .type(MediaType.APPLICATION_JSON) + .header("total-results", traversalUriHttpEntry.getTotalVertices()) + .header("total-pages", traversalUriHttpEntry.getTotalPaginationBuckets()) + .entity(result) + .build(); + }else { + response = Response.status(Status.OK) + .type(MediaType.APPLICATION_JSON) + .entity(result).build(); + } + } catch (AAIException e) { response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e); } catch (Exception e) { diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java b/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java index 7ce61e3..633bc9c 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java @@ -23,8 +23,10 @@ import java.net.URI; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; @@ -118,7 +120,7 @@ public class QueryConsumer extends RESTAPI { @PUT @Consumes({ MediaType.APPLICATION_JSON}) @Produces({ MediaType.APPLICATION_JSON}) - public Response executeQuery(String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("graphson") @QueryParam("format") String queryFormat,@DefaultValue("no_op") @QueryParam("subgraph") String subgraph, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req){ + public Response executeQuery(String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("graphson") @QueryParam("format") String queryFormat,@DefaultValue("no_op") @QueryParam("subgraph") String subgraph, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req, @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, @DefaultValue("-1") @QueryParam("resultSize") String resultSize){ return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, @@ -128,14 +130,13 @@ public class QueryConsumer extends RESTAPI { new AaiCallable() { @Override public Response process() { - return processExecuteQuery(content, versionParam, uri, queryFormat, subgraph, headers, info, req); + return processExecuteQuery(content, versionParam, uri, queryFormat, subgraph, headers, info, req, resultIndex, resultSize); } } ); } - public Response processExecuteQuery(String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("graphson") @QueryParam("format") String queryFormat,@DefaultValue("no_op") @QueryParam("subgraph") String subgraph, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { - + public Response processExecuteQuery(String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("graphson") @QueryParam("format") String queryFormat,@DefaultValue("no_op") @QueryParam("subgraph") String subgraph, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req, @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, @DefaultValue("-1") @QueryParam("resultSize") String resultSize) { String methodName = "executeQuery"; String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); String realTime = headers.getRequestHeaders().getFirst("Real-Time"); @@ -165,6 +166,11 @@ public class QueryConsumer extends RESTAPI { SchemaVersion version = new SchemaVersion(versionParam); DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime); traversalUriHttpEntry.setHttpEntryProperties(version, type); + /* + * Changes for Pagination + */ + + traversalUriHttpEntry.setPaginationParameters(resultIndex, resultSize); dbEngine = traversalUriHttpEntry.getDbEngine(); if (startElement != null) { @@ -188,9 +194,17 @@ public class QueryConsumer extends RESTAPI { CustomQueryConfig customQueryConfig = getCustomQueryConfig(queryURIObj); if ( customQueryConfig != null ) { List missingRequiredQueryParameters = checkForMissingQueryParameters( customQueryConfig.getQueryRequiredProperties(), URITools.getQueryMap(queryURIObj)); + if ( !missingRequiredQueryParameters.isEmpty() ) { return( createMessageMissingQueryRequiredParameters( missingRequiredQueryParameters, headers, info, req)); } + + List invalidQueryParameters = checkForInvalidQueryParameters( customQueryConfig, URITools.getQueryMap(queryURIObj)); + + if ( !invalidQueryParameters.isEmpty() ) { + return( createMessageInvalidQueryParameters( invalidQueryParameters, headers, info, req)); + } + } else if ( queryElement != null ) { return( createMessageInvalidQuerySection( queryURI, headers, info, req)); } @@ -227,8 +241,9 @@ public class QueryConsumer extends RESTAPI { .processWith(processorType).create(); } String result = ""; - List vertices = processor.execute(subGraphStyle); - + List vertTemp = processor.execute(subGraphStyle); + List vertices = traversalUriHttpEntry.getPaginatedVertexList(vertTemp); + DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth); FormatFactory ff = new FormatFactory(traversalUriHttpEntry.getLoader(), serializer, schemaVersions, this.basePath); @@ -240,12 +255,19 @@ public class QueryConsumer extends RESTAPI { LoggingContext.elapsedTime((long)msecs,TimeUnit.MILLISECONDS); LoggingContext.successStatusFields(); LOGGER.info ("Completed"); - - - response = Response.status(Status.OK) - .type(MediaType.APPLICATION_JSON) - .entity(result).build(); + if(traversalUriHttpEntry.isPaginated()){ + response = Response.status(Status.OK) + .type(MediaType.APPLICATION_JSON) + .header("total-results", traversalUriHttpEntry.getTotalVertices()) + .header("total-pages", traversalUriHttpEntry.getTotalPaginationBuckets()) + .entity(result) + .build(); + }else { + response = Response.status(Status.OK) + .type(MediaType.APPLICATION_JSON) + .entity(result).build(); + } } catch (AAIException e) { response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); } catch (Exception e ) { @@ -340,6 +362,44 @@ public class QueryConsumer extends RESTAPI { return response; } + + + public List checkForInvalidQueryParameters( CustomQueryConfig customQueryConfig, MultivaluedMap queryParams) { + + List allParameters = new ArrayList(); + /* + * Add potential Required and Optional to allParameters + */ + Optional.ofNullable(customQueryConfig.getQueryOptionalProperties()).ifPresent(allParameters::addAll); + Optional.ofNullable(customQueryConfig.getQueryRequiredProperties()).ifPresent(allParameters::addAll); + + if(queryParams.isEmpty()) + return new ArrayList<>(); + List invalidParameters = queryParams.keySet().stream() + .filter(param -> !allParameters.contains(param)) + .collect(Collectors.toList()); + + return invalidParameters; + + } + + private Response createMessageInvalidQueryParameters(List invalidQueryParams, HttpHeaders headers, UriInfo info, HttpServletRequest req) { + AAIException e = new AAIException("AAI_3022"); + + ArrayList templateVars = new ArrayList<>(); + + if (templateVars.isEmpty()) { + templateVars.add(invalidQueryParams.toString()); + } + + Response response = Response + .status(e.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, + templateVars)).build(); + + return response; + } + } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/RecentAPIConsumer.java b/aai-traversal/src/main/java/org/onap/aai/rest/RecentAPIConsumer.java index 46bccdf..3154087 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/RecentAPIConsumer.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/RecentAPIConsumer.java @@ -224,8 +224,13 @@ public class RecentAPIConsumer extends RESTAPI { if (params != null && params.containsKey("hours") && params.getFirst("hours").matches("-?\\d+")) { isHoursParameter = true; - - Long hours = Long.parseLong(params.getFirst("hours")); + Long hours = 0L; + try{ + hours = Long.parseLong(params.getFirst("hours")); + } + catch(NumberFormatException ex){ + throw new AAIException("AAI_3021", " Invalid Hours. Valid values for hours are 1 to " + AAIConstants.HISTORY_MAX_HOURS); + } if (hours < 1 || hours > AAIConstants.HISTORY_MAX_HOURS) { throw new AAIException("AAI_3021", " Valid values for hours are 1 to " + AAIConstants.HISTORY_MAX_HOURS); } @@ -233,7 +238,13 @@ public class RecentAPIConsumer extends RESTAPI { if (params != null && params.containsKey("date-time") && params.getFirst("date-time").matches("-?\\d+")) { isDateTimeParameter = true; Long minStartTime = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(AAIConstants.HISTORY_MAX_HOURS); - Long startTime = Long.parseLong(params.getFirst("date-time")); + Long startTime = 0L; + try{ + startTime = Long.parseLong(params.getFirst("date-time")); + } + catch(NumberFormatException ex){ + throw new AAIException("AAI_3021", " Invalid Data-time. Valid values for date-time are "+minStartTime+" to " + System.currentTimeMillis() ); + } if (startTime < minStartTime) { throw new AAIException("AAI_3021", " Valid values for date-time are "+minStartTime+" to " + System.currentTimeMillis() ); } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslContext.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslContext.java index 3a3cc96..9ffa69b 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslContext.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslContext.java @@ -19,8 +19,10 @@ */ package org.onap.aai.rest.dsl; +import java.util.ArrayList; import java.util.Deque; import java.util.LinkedList; +import java.util.List; import org.antlr.v4.runtime.ParserRuleContext; @@ -28,8 +30,12 @@ public class DslContext { private ParserRuleContext ctx; + private boolean validationFlag = true; + private boolean isStartNode = false; + private String startNode = ""; + private List startNodeKeys = new ArrayList(); + private String currentNode; - private String previousNode; private boolean isTraversal = false; @@ -38,7 +44,7 @@ public class DslContext { private boolean isUnionStart = false; private String whereStartNode = ""; - + private Deque unionStartNodes = new LinkedList(); /* @@ -55,6 +61,26 @@ public class DslContext { this.ctx = ctx; } + public boolean isStartNode() { + return isStartNode; + } + + public void setStartNodeFlag(boolean isStartNode) { + this.isStartNode = isStartNode; + } + + public String getStartNode() { + return startNode; + } + + public void setStartNode(String startNode) { + this.startNode = startNode; + } + + public List getStartNodeKeys() { + return startNodeKeys; + } + public String getCurrentNode() { return currentNode; } @@ -126,5 +152,13 @@ public class DslContext { public void setLimitQuery(StringBuilder limitQuery) { this.limitQuery = limitQuery; } + + public boolean isValidationFlag() { + return validationFlag; + } + + public void setValidationFlag(boolean validationFlag) { + this.validationFlag = validationFlag; + } } 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 ecd04ac..a6be24c 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 @@ -29,9 +29,17 @@ import java.util.List; import org.antlr.v4.runtime.tree.TerminalNode; 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.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; @@ -54,18 +62,32 @@ public class DslListener extends AAIDslBaseListener { * Instantiates a new DslListener. */ @Autowired - public DslListener(EdgeIngestor edgeIngestor) { + public DslListener(EdgeIngestor edgeIngestor, SchemaVersions schemaVersions, LoaderFactory loaderFactory) { this.edgeRules = edgeIngestor; context = new DslContext(); - dslBuilder = new DslQueryBuilder(edgeIngestor); + + Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); + dslBuilder = new DslQueryBuilder(edgeIngestor, loader); } - public String getQuery() { + public String getQuery() throws AAIException { + if (!getException().isEmpty()) { + LOGGER.error("Exception in the DSL Query" + getException()); + throw new AAIException("AAI_6149", getException()); + } return dslBuilder.getQuery().toString(); } + public String getException() { + return dslBuilder.getQueryException().toString(); + } + @Override public void enterAaiquery(AAIDslParser.AaiqueryContext ctx) { + /* + * This is my start-node, have some validations here + */ + context.setStartNodeFlag(true); dslBuilder.start(); } @@ -131,6 +153,14 @@ public class DslListener extends AAIDslBaseListener { @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)); + } + } + context.setStartNodeFlag(false); context.setCtx(ctx); dslBuilder.store(context); } @@ -186,6 +216,7 @@ public class DslListener extends AAIDslBaseListener { @Override public void enterFilterStep(AAIDslParser.FilterStepContext ctx) { + context.setCtx(ctx); dslBuilder.filter(context); } @@ -210,4 +241,13 @@ public class DslListener extends AAIDslBaseListener { context.setCtx(ctx); dslBuilder.limit(context); } + + public void setValidationFlag(boolean validationFlag) { + this.context.setValidationFlag(validationFlag); + } + + public boolean isValidationFlag() { + return this.context.isValidationFlag(); + } + } 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 59f4443..fce8a98 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 @@ -21,6 +21,7 @@ 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; @@ -32,15 +33,24 @@ import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.edges.EdgeRuleQuery; import org.onap.aai.edges.enums.EdgeType; import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; + +import com.jcabi.log.Logger; public class DslQueryBuilder { private StringBuilder query; + private StringBuilder queryException; private final EdgeIngestor edgeRules; + private final Loader loader; - public DslQueryBuilder(EdgeIngestor edgeIngestor) { + public DslQueryBuilder(EdgeIngestor edgeIngestor, Loader loader) { this.edgeRules = edgeIngestor; + this.loader = loader; query = new StringBuilder(); + queryException = new StringBuilder(); } public StringBuilder getQuery() { @@ -51,6 +61,14 @@ public class DslQueryBuilder { this.query = query; } + public StringBuilder getQueryException() { + return queryException; + } + + public void setQueryException(StringBuilder queryException) { + this.queryException = queryException; + } + public DslQueryBuilder start() { query.append("builder"); return this; @@ -68,6 +86,8 @@ public class DslQueryBuilder { 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; } @@ -76,7 +96,7 @@ public class DslQueryBuilder { String edgeType = ""; if (!edgeRules.hasRule(baseQ.build())) { throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + context.getPreviousNode() - + ", " + context.getCurrentNode()); + + ", " + context.getCurrentNode()); } else if (edgeRules.hasRule(baseQ.edgeType(EdgeType.TREE).build())) { edgeType = "EdgeType.TREE"; } else if (edgeRules.hasRule(baseQ.edgeType(EdgeType.COUSIN).build())) { @@ -85,7 +105,7 @@ public class DslQueryBuilder { edgeType = "EdgeType.COUSIN"; query.append(".createEdgeTraversal(").append(edgeType).append(", '").append(context.getPreviousNode()) - .append("','").append(context.getCurrentNode()).append("')"); + .append("','").append(context.getCurrentNode()).append("')"); return this; } @@ -142,21 +162,53 @@ public class DslQueryBuilder { } + 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(); - - query.append(key); + /* + * 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 nodes = ctx.KEY(); + List numberValues = ctx.NODE(); + /* + * Add all String values + */ List valuesArray = nodes.stream().filter((node) -> !key.equals(node.getText())) - .map((node) -> "'" + node.getText().replace("'", "").trim() + "'") - .collect(Collectors.toList()); + .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 + * 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); 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 b2be402..d9ce63e 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 @@ -30,7 +30,7 @@ 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; @@ -46,13 +46,14 @@ public class DslQueryProcessor { private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DslQueryProcessor.class); private DslListener dslListener; + private boolean validationFlag = true; @Autowired - public DslQueryProcessor(DslListener dslListener){ + public DslQueryProcessor(DslListener dslListener) { this.dslListener = dslListener; } - public String parseAaiQuery(String aaiQuery) { + public String parseAaiQuery(String aaiQuery) throws AAIException { try { // Create a input stream that reads our string InputStream stream = new ByteArrayInputStream(aaiQuery.getBytes(StandardCharsets.UTF_8)); @@ -63,10 +64,10 @@ public class DslQueryProcessor { // 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); + dslListener.setValidationFlag(isValidationFlag()); // Specify our entry point ParseTree ptree = parser.aaiquery(); LOGGER.info("QUERY-interim" + ptree.toStringTree(parser)); @@ -82,9 +83,17 @@ public class DslQueryProcessor { * */ return dslListener.getQuery(); + } catch (AAIException e) { + throw new AAIException("AAI_6149", "Error while processing the query :" + e.getMessage()); } catch (Exception e) { - LOGGER.error("Error while processing the query"+e.getMessage()); + throw new AAIException("AAI_6149","Error while processing the query :" + e.getMessage()); } - return ""; + } + public boolean isValidationFlag() { + return validationFlag; + } + + public void setValidationFlag(boolean validationFlag) { + this.validationFlag = validationFlag; } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/CQConfig.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/CQConfig.java new file mode 100644 index 0000000..d17fb2b --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/CQConfig.java @@ -0,0 +1,28 @@ +/** + * ============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; + +public abstract class CQConfig { + protected GetCustomQueryConfig queryConfig; + + public GetCustomQueryConfig getCustomQueryConfig(){ + return queryConfig; + } +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/GenericQueryProcessor.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/GenericQueryProcessor.java index fd9d53b..56b748c 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/search/GenericQueryProcessor.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/GenericQueryProcessor.java @@ -27,11 +27,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.javatuples.Pair; -import org.onap.aai.config.SpringContextAware; import org.onap.aai.exceptions.AAIException; import org.onap.aai.query.builder.MissingOptionalParameter; import org.onap.aai.rest.dsl.DslQueryProcessor; -import org.onap.aai.restcore.search.GroovyQueryBuilderSingleton; +import org.onap.aai.restcore.search.GroovyQueryBuilder; import org.onap.aai.restcore.util.URITools; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.serialization.queryformats.SubGraphStyle; @@ -55,7 +54,7 @@ public abstract class GenericQueryProcessor { protected Optional gremlin; protected final TransactionalGraphEngine dbEngine; protected GremlinServerSingleton gremlinServerSingleton; - protected static GroovyQueryBuilderSingleton queryBuilderSingleton = GroovyQueryBuilderSingleton.getInstance(); + protected GroovyQueryBuilder groovyQueryBuilder = new GroovyQueryBuilder(); protected final boolean isGremlin; protected Optional dslQueryProcessorOptional; /* dsl parameters to store dsl query and to check @@ -130,7 +129,7 @@ public abstract class GenericQueryProcessor { String dslUserQuery = dsl.get(); if(dslQueryProcessorOptional.isPresent()){ String dslQuery = dslQueryProcessorOptional.get().parseAaiQuery(dslUserQuery); - query = queryBuilderSingleton.executeTraversal(dbEngine, dslQuery, params); + query = groovyQueryBuilder.executeTraversal(dbEngine, dslQuery, params); String startPrefix = "g.V()"; query = startPrefix + query; } @@ -179,7 +178,7 @@ public abstract class GenericQueryProcessor { if (query == null) { query = ""; } else { - query = queryBuilderSingleton.executeTraversal(dbEngine, query, params); + query = groovyQueryBuilder.executeTraversal(dbEngine, query, params); } String startPrefix = "g.V(startVertexes)"; diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/GremlinServerSingleton.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/GremlinServerSingleton.java index 20a18d9..9ae3dec 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/search/GremlinServerSingleton.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/GremlinServerSingleton.java @@ -25,6 +25,7 @@ import org.onap.aai.util.FileWatcher; import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; import org.apache.tinkerpop.gremlin.driver.Cluster; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import javax.annotation.PostConstruct; @@ -47,11 +48,8 @@ public class GremlinServerSingleton { private boolean timerSet; private Timer timer; - private GetCustomQueryConfig queryConfig; - - @Value("${schema.queries.location}") - private String storedQueriesLocation; + CQConfig customQueryInfo; /** * Initializes the gremlin server singleton * Loads the configuration of the gremlin server and creates a cluster @@ -61,41 +59,9 @@ public class GremlinServerSingleton { * the properties object * */ - @PostConstruct - public void init() { - - try { - String filepath = storedQueriesLocation + AAIConstants.AAI_FILESEP + "stored-queries.json"; - Path path = Paths.get(filepath); - String customQueryConfigJson = new String(Files.readAllBytes(path)); - - - queryConfig = new GetCustomQueryConfig(customQueryConfigJson); - } catch (IOException e) { - logger.error("Error occurred during the processing of query json file: " + LogFormatTools.getStackTop(e)); - } - - - TimerTask task = new FileWatcher(new File(storedQueriesLocation)) { - @Override - protected void onChange(File file) { - try { - String filepath = storedQueriesLocation; - Path path = Paths.get(filepath); - String customQueryConfigJson = new String(Files.readAllBytes(path)); - queryConfig = new GetCustomQueryConfig(customQueryConfigJson); - } catch (IOException e) { - logger.error("Error occurred during the processing of query json file: " + LogFormatTools.getStackTop(e)); - } - } - }; - - if (!timerSet) { - timerSet = true; - timer = new Timer(); - timer.schedule( task , new Date(), 10000 ); - } - + @Autowired + public GremlinServerSingleton(CQConfig customQueryInfo){ + this.customQueryInfo = customQueryInfo; } /** @@ -104,6 +70,8 @@ public class GremlinServerSingleton { * @return */ public String getStoredQueryFromConfig(String key){ + GetCustomQueryConfig queryConfig = customQueryInfo.getCustomQueryConfig(); + CustomQueryConfig customQueryConfig = queryConfig.getStoredQuery(key); if ( customQueryConfig == null ) { return null; @@ -112,6 +80,7 @@ public class GremlinServerSingleton { } public CustomQueryConfig getCustomQueryConfig(String key) { + GetCustomQueryConfig queryConfig = customQueryInfo.getCustomQueryConfig(); return queryConfig.getStoredQuery(key); } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/GroovyShellImpl.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/GroovyShellImpl.java index de59262..712d7f0 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/search/GroovyShellImpl.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/GroovyShellImpl.java @@ -23,7 +23,7 @@ import java.util.Map; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.onap.aai.restcore.search.GremlinGroovyShellSingleton; +import org.onap.aai.restcore.search.GremlinGroovyShell; public class GroovyShellImpl extends GenericQueryProcessor { @@ -36,7 +36,7 @@ public class GroovyShellImpl extends GenericQueryProcessor { params.put("g", this.dbEngine.asAdmin().getTraversalSource()); - GremlinGroovyShellSingleton shell = GremlinGroovyShellSingleton.getInstance(); + GremlinGroovyShell shell = new GremlinGroovyShell(); return shell.executeTraversal(query, params); } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/LocalCQConfig.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/LocalCQConfig.java new file mode 100644 index 0000000..bcd4c4e --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/LocalCQConfig.java @@ -0,0 +1,85 @@ +/** + * ============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 com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.onap.aai.logging.LogFormatTools; +import org.onap.aai.util.AAIConstants; +import org.onap.aai.util.FileWatcher; +import org.springframework.beans.factory.annotation.Value; + +import javax.annotation.PostConstruct; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +public class LocalCQConfig extends CQConfig { + private static EELFLogger logger = EELFManager.getInstance().getLogger(LocalCQConfig.class); + + @Value("${schema.queries.location}") + private String storedQueriesLocation; + + private boolean timerSet; + private Timer timer; + + @PostConstruct + public void init() { + + try { + String filepath = storedQueriesLocation + AAIConstants.AAI_FILESEP + "stored-queries.json"; + logger.info("Using the Local stored queries"); + Path path = Paths.get(filepath); + String customQueryConfigJson = new String(Files.readAllBytes(path)); + queryConfig = new GetCustomQueryConfig(customQueryConfigJson); + + } catch (IOException e) { + logger.error("Error occurred during the processing of query json file: " + LogFormatTools.getStackTop(e)); + } + + TimerTask task = new FileWatcher(new File(storedQueriesLocation)) { + @Override + protected void onChange(File file) { + try { + String filepath = storedQueriesLocation; + Path path = Paths.get(filepath); + String customQueryConfigJson = new String(Files.readAllBytes(path)); + queryConfig = new GetCustomQueryConfig(customQueryConfigJson); + + } catch (IOException e) { + logger.error("Error occurred during the processing of query json file: " + LogFormatTools.getStackTop(e)); + } + } + }; + + if (!timerSet) { + timerSet = true; + timer = new Timer(); + timer.schedule(task, new Date(), 10000); + } + + } + +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/NodeQueryProcessor.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/NodeQueryProcessor.java index 0126162..6421f67 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/search/NodeQueryProcessor.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/NodeQueryProcessor.java @@ -28,7 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.javatuples.Pair; import org.onap.aai.exceptions.AAIException; -import org.onap.aai.restcore.search.GroovyQueryBuilderSingleton; +import org.onap.aai.restcore.search.GroovyQueryBuilder; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.serialization.queryformats.SubGraphStyle; @@ -49,7 +49,7 @@ public class NodeQueryProcessor extends GroovyShellImpl { protected static Pattern p = Pattern.compile("query/(.*+)"); protected Optional gremlin; protected final TransactionalGraphEngine dbEngine; - protected static GroovyQueryBuilderSingleton queryBuilderSingleton = GroovyQueryBuilderSingleton.getInstance();; + protected GroovyQueryBuilder queryBuilder = new GroovyQueryBuilder();; protected NodeQueryProcessor(Builder builder) { super(builder); @@ -82,7 +82,7 @@ public class NodeQueryProcessor extends GroovyShellImpl { params.put("startTime", startTime); params.put("nodeType", nodeType); - query = queryBuilderSingleton.executeTraversal(dbEngine, query, params); + query = queryBuilder.executeTraversal(dbEngine, query, params); String startPrefix = "g.V()"; diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/SchemaServiceCQConfig.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/SchemaServiceCQConfig.java new file mode 100644 index 0000000..6e55246 --- /dev/null +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/SchemaServiceCQConfig.java @@ -0,0 +1,64 @@ +/** + * ============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 com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.onap.aai.restclient.RestClient; +import org.onap.aai.restclient.RestClientFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; + +import javax.annotation.PostConstruct; +import java.util.HashMap; +import java.util.Map; + +public class SchemaServiceCQConfig extends CQConfig { + + private static EELFLogger logger = EELFManager.getInstance().getLogger(SchemaServiceCQConfig.class); + private static final String SCHEMA_SERVICE = "schema-service"; + + @Value("${schema.service.custom.queries.endpoint}") + private String customQueriesUri; + + @Autowired + private RestClientFactory restClientFactory; + + @PostConstruct + public void initialize() { + //Call SchemaService to get custom queries + retrieveCustomQueries(); + } + + public void retrieveCustomQueries() { + /* + Call Schema MS to get custom queries using RestTemplate + */ + logger.info("Calling the SchemaService to retrieve stored queries"); + String content = ""; + Map headersMap = new HashMap<>(); + RestClient restClient = restClientFactory + .getRestClient(SCHEMA_SERVICE); + + ResponseEntity schemaResponse = restClient.getGetRequest(content, customQueriesUri, headersMap); + queryConfig = new GetCustomQueryConfig(schemaResponse.getBody()); + } +} diff --git a/aai-traversal/src/main/java/org/onap/aai/util/TraversalConstants.java b/aai-traversal/src/main/java/org/onap/aai/util/TraversalConstants.java index 69e1e9f..4b5ebfe 100644 --- a/aai-traversal/src/main/java/org/onap/aai/util/TraversalConstants.java +++ b/aai-traversal/src/main/java/org/onap/aai/util/TraversalConstants.java @@ -29,6 +29,8 @@ public final class TraversalConstants { public static final String AAI_TRAVERSAL_DSL_TIMEOUT_LIMIT = "aai.traversal.dsl.timeoutlimit"; public static final String AAI_TRAVERSAL_DSL_TIMEOUT_ENABLED = "aai.traversal.dsl.timeoutenabled"; public static final String AAI_TRAVERSAL_DSL_TIMEOUT_APP = "aai.traversal.dsl.timeout.appspecific"; + public static final String DSL_NOVALIDATION_CLIENTS = "aai.traversal.dsl.novalidation.clients"; + public static final String DSL_OVERRIDE = "aai.dsl.override"; public static final long HISTORY_MAX_HOURS = 192; -- cgit 1.2.3-korg