diff options
author | Fiete Ostkamp <Fiete.Ostkamp@telekom.de> | 2022-10-05 09:55:45 +0200 |
---|---|---|
committer | Fiete Ostkamp <Fiete.Ostkamp@telekom.de> | 2022-10-05 09:55:45 +0200 |
commit | e632cf8afa27bdedf8b2044c430cd604ab7d4987 (patch) | |
tree | 85cf35932109fd858e09f4bf1a0a5d0724057697 /aai-traversal/src/main/java | |
parent | 20ea11d8067c57fe47d9bdc64663b8cc8a5742ca (diff) |
Run the formatter for the traversal service
When building the traversal service with mvn install, the spotless and formatter plugins are invoked to verify the formatting.
This results in 40000 lines of format violations that are printed out to the console.
By invoking mvn formatter:format spotless:apply process-sources this number can be reduced to 2000 lines of format violations.
Issue-ID: AAI-3543
Signed-off-by: Fiete Ostkamp <Fiete.Ostkamp@telekom.de>
Change-Id: Id0011b3e0a626369c79fd0656cd44455347b7fde
Diffstat (limited to 'aai-traversal/src/main/java')
86 files changed, 8914 insertions, 8624 deletions
diff --git a/aai-traversal/src/main/java/org/onap/aai/Profiles.java b/aai-traversal/src/main/java/org/onap/aai/Profiles.java index 25f51c3..0a886af 100644 --- a/aai-traversal/src/main/java/org/onap/aai/Profiles.java +++ b/aai-traversal/src/main/java/org/onap/aai/Profiles.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -21,15 +21,16 @@ package org.onap.aai; public final class Profiles { - public static final String DMAAP = "dmaap"; - public static final String DME2 = "dme2"; + public static final String DMAAP = "dmaap"; + public static final String DME2 = "dme2"; - public static final String ONE_WAY_SSL = "one-way-ssl"; + public static final String ONE_WAY_SSL = "one-way-ssl"; // AAF Basic Auth - public static final String AAF_AUTHENTICATION = "aaf-auth"; + public static final String AAF_AUTHENTICATION = "aaf-auth"; // AAF Auth with Client Certs - public static final String AAF_CERT_AUTHENTICATION = "aaf-cert-auth"; - public static final String TWO_WAY_SSL = "two-way-ssl"; + public static final String AAF_CERT_AUTHENTICATION = "aaf-cert-auth"; + public static final String TWO_WAY_SSL = "two-way-ssl"; - private Profiles(){} + private Profiles() { + } } 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 56573bc..5ac3ff1 100644 --- a/aai-traversal/src/main/java/org/onap/aai/TraversalApp.java +++ b/aai-traversal/src/main/java/org/onap/aai/TraversalApp.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,6 +19,11 @@ */ package org.onap.aai; +import java.util.Map; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + import org.apache.commons.lang3.exception.ExceptionUtils; import org.onap.aai.aailog.logs.AaiDebugLog; import org.onap.aai.config.PropertyPasswordConfiguration; @@ -41,164 +46,154 @@ import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurat import org.springframework.context.annotation.ComponentScan; import org.springframework.core.env.Environment; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -import java.util.Map; - -@SpringBootApplication(exclude = { - DataSourceAutoConfiguration.class, - DataSourceTransactionManagerAutoConfiguration.class, - HibernateJpaAutoConfiguration.class -}) +@SpringBootApplication( + exclude = {DataSourceAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) // Component Scan provides a way to look for spring beans // It only searches beans in the following packages // Any method annotated with @Bean annotation or any class // with @Component, @Configuration, @Service will be picked up -@ComponentScan(basePackages = { - "org.onap.aai.config", - "org.onap.aai.web", - "org.onap.aai.setup", - "org.onap.aai.tasks", - "org.onap.aai.service", - "org.onap.aai.rest", - "org.onap.aai.aaf", - "org.onap.aai.aailog" -}) +@ComponentScan( + basePackages = {"org.onap.aai.config", "org.onap.aai.web", "org.onap.aai.setup", + "org.onap.aai.tasks", "org.onap.aai.service", "org.onap.aai.rest", "org.onap.aai.aaf", + "org.onap.aai.aailog"}) public class TraversalApp { - private static final Logger logger = LoggerFactory.getLogger(TraversalApp.class.getName()); - - private static AaiDebugLog debugLog = new AaiDebugLog(); - static { - debugLog.setupMDC(); - } - - private static final String APP_NAME = "aai-traversal"; - private static Map<String,String> contextMap; - - @Autowired - private Environment env; - - @Autowired - private NodeIngestor nodeIngestor; - - @Autowired - private SpringContextAware context; - - @Autowired - private SpringContextAware loaderFactory; - - - @PostConstruct - private void init() throws AAIException { - System.setProperty("org.onap.aai.serverStarted", "false"); - setDefaultProps(); - - contextMap = MDC.getCopyOfContextMap(); - - logger.debug("AAI Server initialization started..."); - - // Setting this property to allow for encoded slash (/) in the path parameter - // This is only needed for tomcat keeping this as temporary - System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"); - - logger.debug("Starting AAIGraph connections and the NodeInjestor"); - - if(env.acceptsProfiles(Profiles.TWO_WAY_SSL) && env.acceptsProfiles(Profiles.ONE_WAY_SSL)){ - logger.debug("You have seriously misconfigured your application"); - } - - AAIConfig.init(); - - AAIGraph.getInstance(); - } - - @PreDestroy - public void cleanup(){ - logger.debug("Traversal MicroService stopped"); - logger.info("Shutting down both realtime and cached connections"); - AAIGraph.getInstance().graphShutdown(); - } - - public static void main(String[] args) throws AAIException{ - - setDefaultProps(); - - 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); - ErrorLogHelper.logException(aai); - ErrorLogHelper.logError(aai.getCode(), ex.getMessage() + ", resolve and restart Traversal"); - throw aai; - } - - - MDC.setContextMap (contextMap); - logger.info( - "Application '{}' is running on {}!" , - env.getProperty("spring.application.name"), - env.getProperty("server.port") - ); - - logger.debug("Traversal MicroService Started"); - System.out.println("Traversal Microservice Started"); - } - - public static void setDefaultProps(){ - - if (System.getProperty("file.separator") == null) { - System.setProperty("file.separator", "/"); - } - - String currentDirectory = System.getProperty("user.dir"); - System.setProperty("aai.service.name", TraversalApp.class.getSimpleName()); - - if (System.getProperty("AJSC_HOME") == null) { - System.setProperty("AJSC_HOME", "."); - } - - if(currentDirectory.contains(APP_NAME)){ - if (System.getProperty("BUNDLECONFIG_DIR") == null) { - System.setProperty("BUNDLECONFIG_DIR", "src/main/resources"); - } - } else { - if (System.getProperty("BUNDLECONFIG_DIR") == null) { - System.setProperty("BUNDLECONFIG_DIR", "aai-traversal/src/main/resources"); - } - } - - } - private static AAIException schemaServiceExceptionTranslator(Exception ex) { - AAIException aai = null; - logger.info("Error Message is {} details - {}", ExceptionUtils.getRootCause(ex).toString(), ExceptionUtils.getRootCause(ex).getMessage()); - if ( ExceptionUtils.getRootCause(ex) == null || ExceptionUtils.getRootCause(ex).getMessage() == null ) { - aai = new AAIException("AAI_3025","Error parsing exception - Please Investigate" + - LogFormatTools.getStackTop(ex)); + private static final Logger logger = LoggerFactory.getLogger(TraversalApp.class.getName()); + + private static AaiDebugLog debugLog = new AaiDebugLog(); + static { + debugLog.setupMDC(); + } + + private static final String APP_NAME = "aai-traversal"; + private static Map<String, String> contextMap; + + @Autowired + private Environment env; + + @Autowired + private NodeIngestor nodeIngestor; + + @Autowired + private SpringContextAware context; + + @Autowired + private SpringContextAware loaderFactory; + + @PostConstruct + private void init() throws AAIException { + System.setProperty("org.onap.aai.serverStarted", "false"); + setDefaultProps(); + + contextMap = MDC.getCopyOfContextMap(); + + logger.debug("AAI Server initialization started..."); + + // Setting this property to allow for encoded slash (/) in the path parameter + // This is only needed for tomcat keeping this as temporary + System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"); + + logger.debug("Starting AAIGraph connections and the NodeInjestor"); + + if (env.acceptsProfiles(Profiles.TWO_WAY_SSL) + && env.acceptsProfiles(Profiles.ONE_WAY_SSL)) { + logger.debug("You have seriously misconfigured your application"); + } + + AAIConfig.init(); + + AAIGraph.getInstance(); + } + + @PreDestroy + public void cleanup() { + logger.debug("Traversal MicroService stopped"); + logger.info("Shutting down both realtime and cached connections"); + AAIGraph.getInstance().graphShutdown(); + } + + public static void main(String[] args) throws AAIException { + + setDefaultProps(); + + 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); + ErrorLogHelper.logException(aai); + ErrorLogHelper.logError(aai.getCode(), + ex.getMessage() + ", resolve and restart Traversal"); + throw aai; + } + + MDC.setContextMap(contextMap); + logger.info("Application '{}' is running on {}!", + env.getProperty("spring.application.name"), env.getProperty("server.port")); + + logger.debug("Traversal MicroService Started"); + System.out.println("Traversal Microservice Started"); + } + + public static void setDefaultProps() { + + if (System.getProperty("file.separator") == null) { + System.setProperty("file.separator", "/"); + } + + String currentDirectory = System.getProperty("user.dir"); + System.setProperty("aai.service.name", TraversalApp.class.getSimpleName()); + + if (System.getProperty("AJSC_HOME") == null) { + System.setProperty("AJSC_HOME", "."); + } + + if (currentDirectory.contains(APP_NAME)) { + if (System.getProperty("BUNDLECONFIG_DIR") == null) { + System.setProperty("BUNDLECONFIG_DIR", "src/main/resources"); + } + } else { + if (System.getProperty("BUNDLECONFIG_DIR") == null) { + System.setProperty("BUNDLECONFIG_DIR", "aai-traversal/src/main/resources"); + } + } + + } + + private static AAIException schemaServiceExceptionTranslator(Exception ex) { + AAIException aai = null; + logger.info("Error Message is {} details - {}", ExceptionUtils.getRootCause(ex).toString(), + ExceptionUtils.getRootCause(ex).getMessage()); + if (ExceptionUtils.getRootCause(ex) == null + || ExceptionUtils.getRootCause(ex).getMessage() == null) { + aai = new AAIException("AAI_3025", + "Error parsing exception - Please Investigate" + LogFormatTools.getStackTop(ex)); } else { - logger.info("Exception is " + ExceptionUtils.getRootCause(ex).getMessage() + "Root cause is"+ ExceptionUtils.getRootCause(ex).toString()); - 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("Connection refused")){ - aai = new AAIException("AAI_3025","Error connecting to SchemaService - Investigate"); - }else { - aai = new AAIException("AAI_3025","Error connecting to SchemaService - Please Investigate"); - } + logger.info("Exception is " + ExceptionUtils.getRootCause(ex).getMessage() + + "Root cause is" + ExceptionUtils.getRootCause(ex).toString()); + 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("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; - } + return aai; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/aailog/logs/AaiDBTraversalMetricLog.java b/aai-traversal/src/main/java/org/onap/aai/aailog/logs/AaiDBTraversalMetricLog.java index 8afc58b..7b28c7b 100644 --- a/aai-traversal/src/main/java/org/onap/aai/aailog/logs/AaiDBTraversalMetricLog.java +++ b/aai-traversal/src/main/java/org/onap/aai/aailog/logs/AaiDBTraversalMetricLog.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,6 +20,12 @@ package org.onap.aai.aailog.logs; +import java.net.URI; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Optional; + import org.onap.aai.util.AAIConstants; import org.onap.logging.filter.base.Constants; import org.onap.logging.filter.base.MDCSetup; @@ -28,23 +34,17 @@ import org.onap.logging.ref.slf4j.ONAPLogConstants; import org.slf4j.*; import org.springframework.beans.factory.annotation.Value; -import java.net.URI; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Optional; - public class AaiDBTraversalMetricLog extends MDCSetup { protected static final Logger logger = LoggerFactory.getLogger(AaiDBTraversalMetricLog.class); private final String partnerName; private static final Marker INVOKE_RETURN = MarkerFactory.getMarker("INVOKE-RETURN"); private static final String TARGET_ENTITY = ONAPComponents.AAI.toString() + ".DB"; + public AaiDBTraversalMetricLog(String subcomponent) { partnerName = getPartnerName(subcomponent); } - protected String getTargetServiceName(Optional<URI> uri) { return (getServiceName(uri)); } @@ -60,12 +60,11 @@ public class AaiDBTraversalMetricLog extends MDCSetup { return serviceName; } - protected String getTargetEntity(Optional<URI> uri) { return TARGET_ENTITY; } - protected String getPartnerName(@Value(AAIConstants.AAI_TRAVERSAL_MS) String subcomponent ) { + protected String getPartnerName(@Value(AAIConstants.AAI_TRAVERSAL_MS) String subcomponent) { StringBuilder sb = new StringBuilder(ONAPComponents.AAI.toString()).append(subcomponent); return (sb.toString()); } @@ -95,7 +94,8 @@ public class AaiDBTraversalMetricLog extends MDCSetup { } protected void setupMDC(Optional<URI> uri) { - MDC.put("InvokeTimestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + MDC.put("InvokeTimestamp", + ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); MDC.put("TargetServiceName", this.getTargetServiceName(uri)); MDC.put("StatusCode", ONAPLogConstants.ResponseStatus.INPROGRESS.toString()); this.setInvocationIdFromMDC(); 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 d10d4ac..81e96d1 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,6 +19,9 @@ */ package org.onap.aai.config; +import java.util.HashMap; +import java.util.Map; + import org.antlr.v4.runtime.tree.ParseTreeListener; import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.introspection.LoaderFactory; @@ -30,24 +33,24 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; -import java.util.HashMap; -import java.util.Map; - @Configuration public class DslConfiguration { @Bean @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public Map<QueryVersion, ParseTreeListener> dslListeners(EdgeIngestor edgeIngestor, SchemaVersions schemaVersions, LoaderFactory loaderFactory){ + public Map<QueryVersion, ParseTreeListener> dslListeners(EdgeIngestor edgeIngestor, + SchemaVersions schemaVersions, LoaderFactory loaderFactory) { Map<QueryVersion, ParseTreeListener> dslListeners = new HashMap<>(); - dslListeners.put(QueryVersion.V1,new org.onap.aai.rest.dsl.v1.DslListener(edgeIngestor, schemaVersions, loaderFactory)); - dslListeners.put(QueryVersion.V2,new org.onap.aai.rest.dsl.v2.DslListener(edgeIngestor, schemaVersions, loaderFactory)); + dslListeners.put(QueryVersion.V1, + new org.onap.aai.rest.dsl.v1.DslListener(edgeIngestor, schemaVersions, loaderFactory)); + dslListeners.put(QueryVersion.V2, + new org.onap.aai.rest.dsl.v2.DslListener(edgeIngestor, schemaVersions, loaderFactory)); return dslListeners; } @Bean @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) - public DslQueryProcessor dslQueryProcessor(Map<QueryVersion, ParseTreeListener> dslListeners){ + public DslQueryProcessor dslQueryProcessor(Map<QueryVersion, ParseTreeListener> dslListeners) { return new DslQueryProcessor(dslListeners); } } diff --git a/aai-traversal/src/main/java/org/onap/aai/config/ErrorHandler.java b/aai-traversal/src/main/java/org/onap/aai/config/ErrorHandler.java index 22e12a6..40a0eee 100644 --- a/aai-traversal/src/main/java/org/onap/aai/config/ErrorHandler.java +++ b/aai-traversal/src/main/java/org/onap/aai/config/ErrorHandler.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,21 +19,22 @@ */ package org.onap.aai.config; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.logging.ErrorLogHelper; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.MediaType; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; /** * Responsible for dealing with uri that doesn't start with basePath @@ -46,15 +47,17 @@ public class ErrorHandler extends OncePerRequestFilter { private String basePath; - public ErrorHandler(@Value("${schema.uri.base.path}") String basePath){ + public ErrorHandler(@Value("${schema.uri.base.path}") String basePath) { this.basePath = basePath; - if(!basePath.endsWith("/")){ + if (!basePath.endsWith("/")) { this.basePath = basePath + "/"; } } @Override - protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { + protected void doFilterInternal(HttpServletRequest httpServletRequest, + HttpServletResponse httpServletResponse, FilterChain filterChain) + throws ServletException, IOException { String uri = httpServletRequest.getRequestURI(); diff --git a/aai-traversal/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java b/aai-traversal/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java index 944f951..bffb7fb 100644 --- a/aai-traversal/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java +++ b/aai-traversal/src/main/java/org/onap/aai/config/JettyPasswordDecoder.java @@ -8,7 +8,7 @@ * 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 + * 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, diff --git a/aai-traversal/src/main/java/org/onap/aai/config/PasswordDecoder.java b/aai-traversal/src/main/java/org/onap/aai/config/PasswordDecoder.java index 0dcb845..a257b34 100644 --- a/aai-traversal/src/main/java/org/onap/aai/config/PasswordDecoder.java +++ b/aai-traversal/src/main/java/org/onap/aai/config/PasswordDecoder.java @@ -8,7 +8,7 @@ * 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 + * 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, diff --git a/aai-traversal/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java b/aai-traversal/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java index 0a76d6d..5d5a075 100644 --- a/aai-traversal/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java +++ b/aai-traversal/src/main/java/org/onap/aai/config/PropertyPasswordConfiguration.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,6 +19,8 @@ */ package org.onap.aai.config; +import com.att.eelf.configuration.EELFManager; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -29,19 +31,20 @@ import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.att.eelf.configuration.EELFManager; -import org.apache.commons.io.IOUtils; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.*; -public class PropertyPasswordConfiguration implements ApplicationContextInitializer<ConfigurableApplicationContext> { +public class PropertyPasswordConfiguration + implements ApplicationContextInitializer<ConfigurableApplicationContext> { private static final Pattern decodePasswordPattern = Pattern.compile("password\\((.*?)\\)"); private PasswordDecoder passwordDecoder = new JettyPasswordDecoder(); - private static final Logger logger = LoggerFactory.getLogger(PropertyPasswordConfiguration.class.getName()); + private static final Logger logger = + LoggerFactory.getLogger(PropertyPasswordConfiguration.class.getName()); @Override public void initialize(ConfigurableApplicationContext applicationContext) { @@ -113,21 +116,25 @@ public class PropertyPasswordConfiguration implements ApplicationContextInitiali Map<String, Object> propertyOverrides = new LinkedHashMap<>(); decodePasswords(propertySource, propertyOverrides); if (!propertyOverrides.isEmpty()) { - PropertySource<?> decodedProperties = new MapPropertySource("decoded "+ propertySource.getName(), propertyOverrides); - environment.getPropertySources().addBefore(propertySource.getName(), decodedProperties); + PropertySource<?> decodedProperties = + new MapPropertySource("decoded " + propertySource.getName(), propertyOverrides); + environment.getPropertySources().addBefore(propertySource.getName(), + decodedProperties); } } if (!sslProps.isEmpty()) { logger.debug("Using AAF Certman files"); - PropertySource<?> additionalProperties = new MapPropertySource("additionalProperties", sslProps); + PropertySource<?> additionalProperties = + new MapPropertySource("additionalProperties", sslProps); environment.getPropertySources().addFirst(additionalProperties); } } private void decodePasswords(PropertySource<?> source, Map<String, Object> propertyOverrides) { if (source instanceof EnumerablePropertySource) { - EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) source; + EnumerablePropertySource<?> enumerablePropertySource = + (EnumerablePropertySource<?>) source; for (String key : enumerablePropertySource.getPropertyNames()) { Object rawValue = source.getProperty(key); if (rawValue instanceof String) { @@ -139,7 +146,8 @@ public class PropertyPasswordConfiguration implements ApplicationContextInitiali } private String decodePasswordsInString(String input) { - if (input == null) return null; + if (input == null) + return null; StringBuffer output = new StringBuffer(); Matcher matcher = decodePasswordPattern.matcher(input); while (matcher.find()) { 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 5f131bf..248e799 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,7 +20,6 @@ package org.onap.aai.config; import org.onap.aai.dbgraphmap.SearchGraph; - import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.rest.search.CQConfig; @@ -39,30 +38,28 @@ import org.springframework.context.annotation.PropertySource; public class SearchConfiguration { - 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) { - return new SearchGraph(loaderFactory, edgeIngestor, schemaVersions); - } - - @Bean - public GremlinServerSingleton gremlinServerSingleton(){ - return new GremlinServerSingleton(getCustomQueryConfig()); - } + private static final String SCHEMA_SERVICE_TRANSLATOR = "schema-service"; + @Value("${schema.translator.list}") + private String translator; - @Bean - public CQConfig getCustomQueryConfig(){ - if(translator.equals(SCHEMA_SERVICE_TRANSLATOR)) { - return new SchemaServiceCQConfig(); - } - return new LocalCQConfig(); - } + @Bean + public SearchGraph searchGraph(LoaderFactory loaderFactory, EdgeIngestor edgeIngestor, + SchemaVersions schemaVersions) { + return new SearchGraph(loaderFactory, edgeIngestor, schemaVersions); + } + @Bean + public GremlinServerSingleton 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/dbgraphgen/ModelBasedProcessing.java b/aai-traversal/src/main/java/org/onap/aai/dbgraphgen/ModelBasedProcessing.java index de25586..aa4fdad 100644 --- a/aai-traversal/src/main/java/org/onap/aai/dbgraphgen/ModelBasedProcessing.java +++ b/aai-traversal/src/main/java/org/onap/aai/dbgraphgen/ModelBasedProcessing.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,17 +19,20 @@ */ package org.onap.aai.dbgraphgen; -import org.onap.aai.logging.ErrorLogHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.google.common.util.concurrent.SimpleTimeLimiter; import com.google.common.util.concurrent.TimeLimiter; import com.google.common.util.concurrent.UncheckedTimeoutException; + +import java.util.*; +import java.util.concurrent.TimeUnit; + import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.onap.aai.concurrent.AaiCallable; +import org.onap.aai.config.SpringContextAware; import org.onap.aai.db.DbMethHelper; import org.onap.aai.db.props.AAIProperties; import org.onap.aai.dbgen.PropertyLimitDesc; @@ -40,3688 +43,3820 @@ 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 org.onap.aai.logging.ErrorLogHelper; import org.onap.aai.query.builder.QueryBuilder; import org.onap.aai.schema.enums.PropertyMetadata; import org.onap.aai.serialization.db.DBSerializer; - import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.util.AAIConfig; -import org.onap.aai.concurrent.AaiCallable; -import org.onap.aai.config.SpringContextAware; - -import java.util.*; -import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * Utility class that uses Model/Named-Query definitions to navigate the graph. + * Utility class that uses Model/Named-Query definitions to navigate the graph. */ public class ModelBasedProcessing { - private static Logger logger = LoggerFactory.getLogger(ModelBasedProcessing.class); - private static final int MAX_LEVELS = 50; // max depth allowed for our model - to protect against infinite loop problems - - private TransactionalGraphEngine engine; - private Loader loader; - private DBSerializer serializer; - private DbMethHelper dbMethHelper; - - protected ModelBasedProcessing() { - - } - public ModelBasedProcessing(Loader loader, TransactionalGraphEngine engine, DBSerializer serializer) { - this.loader = loader; - this.engine = engine; - this.serializer = serializer; - dbMethHelper = new DbMethHelper(loader, engine); - } - /** - * Gets the start nodes and model-ver's. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param passedModelVersionId the passed model-version-id -- optional (unique id for a model-ver) - * @param passedModelInvId the passed model-invariant-id -- optional - * @param passedModelName the passed model-name -- optional - * @param passedTopNodeType the passed top node type -- optional (needed if neither model=invariant-id nor model-version-id is passed) - * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used to locate the first node(s) of instance data) - * @param apiVer the api ver - * @return HashMap of startNodes and their corresponding model-version-id's - * @throws AAIException the AAI exception - */ - public Map<String,String> getStartNodesAndModVersionIds( String transId, String fromAppId, - String passedModelVersionId, - String passedModelInvId, - String passedModelName, - String passedTopNodeType, - List<Map<String,Object>> startNodeFilterArrayOfHashes, - String apiVer ) - throws AAIException { - // ---------------------------------------------------------------------------------------------------- - // Get a hash for all start-nodes (key = vtxId, val = modelVersionId that applies) - // If no start-node-key info is passed, then use either the passed modelVersion or - // the passed model-invariant-id or model-name to collect them. - // If start-node-key info is given, use it instead to look for start-nodes. - // Note: if ONLY start-node-key info is given, then it would have to map to nodes which - // have persona data. Otherwise we'd have no way to know what model to collect data with. - // ---------------------------------------------------------------------------------------------------- - - Iterator<Vertex> startVerts = null; - Map<String, String> startVertInfo = new HashMap<>(); - - if( startNodeFilterArrayOfHashes.isEmpty() ){ - // Since they did not give any data to find start instances, we will have to find them - // using whatever model-info they provided so we can use it to map to persona-data in the db. - if( (passedModelVersionId == null || passedModelVersionId.equals("")) - && (passedModelInvId == null || passedModelInvId.equals("")) - && (passedModelName == null || passedModelName.equals(""))){ - throw new AAIException("AAI_6118", "ModelInvariantId or ModelName or ModelVersionId required if no startNodeFilter data passed."); - } - else { - // Use whatever model info they pass to find start-node instances - // Get the first/top named-query-element used by this query - if( passedModelVersionId != null && !passedModelVersionId.equals("") ){ - // Need to look up the model-invariant-id and model-version to check against persona data - Vertex modVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", - "model-version-id", passedModelVersionId); - Vertex modVtx = getModelGivenModelVer( modVerVtx, "" ); - String calcModId = modVtx.<String>property("model-invariant-id").orElse(null); - // Now we can look up instances that match this model's info - if( calcModId != null ){ - startVerts = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(addDBAliasedSuffix("model-invariant-id"),calcModId).has(addDBAliasedSuffix("model-version-id"),passedModelVersionId); - } - } - else if( passedModelInvId != null && !passedModelInvId.equals("") ){ - // They gave us the model-invariant-id - startVerts = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(addDBAliasedSuffix("model-invariant-id"),passedModelInvId); - } - else if( passedModelName != null && !passedModelName.equals("") ){ - List<Vertex> modelVerVtxList = getModelVersUsingName(transId, fromAppId, passedModelName); - List<Vertex> startVtxList = new ArrayList<>(); - // Need to look up the model-inv-ids and model-versions to check against persona data - if( !modelVerVtxList.isEmpty() ){ - for( int i = 0; i < modelVerVtxList.size(); i++ ){ - String calcModVerId = (modelVerVtxList.get(i)).<String>property("model-version-id").orElse(null); - Vertex modVtx = getModelGivenModelVer(modelVerVtxList.get(i),""); - String calcModInvId = modVtx.<String>property("model-invariant-id").orElse(null); - // Now we can look up instances that match this model's info - Iterator<Vertex> tmpStartIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(addDBAliasedSuffix("model-invariant-id"),calcModInvId).has(addDBAliasedSuffix("model-version-id"),calcModVerId); - while( tmpStartIter.hasNext() ){ - Vertex tmpStartVert = tmpStartIter.next(); - startVtxList.add(tmpStartVert); - } - } - } - if( !startVtxList.isEmpty() ){ - startVerts = startVtxList.iterator(); - } - } - } - - if( startVerts != null ){ - while( startVerts.hasNext() ){ - Vertex tmpStartVert = startVerts.next(); - String vid = tmpStartVert.id().toString(); - //String tmpModId = tmpStartVert.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null); - String tmpModVerId = tmpStartVert.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); - startVertInfo.put(vid, tmpModVerId); - } - } - if( startVertInfo.isEmpty() ){ - throw new AAIException("AAI_6114", "Start Node(s) could not be found for model data passed. " + - "(modelVersionId = [" + passedModelVersionId + - "], modelInvariantId = [" + passedModelInvId + - "], modelName = [" + passedModelName + - "])"); - } - - return startVertInfo; - } - else { - // Use start-node filter info to find start-node(s) - Note - there could also be model info passed that we'll need - // to use to trim down the set of start-nodes that we find based on the startNodeFilter data. - String modTopNodeType =""; - String modInfoStr = ""; - if( passedModelVersionId != null && !passedModelVersionId.equals("") ){ - modTopNodeType = getModelVerTopWidgetType( transId, fromAppId, passedModelVersionId, "", "" ); - modInfoStr = "modelVersionId = (" + passedModelVersionId + ")"; - } - else if( passedModelInvId != null && !passedModelInvId.equals("") ){ - modTopNodeType = getModelVerTopWidgetType( transId, fromAppId,"", passedModelInvId, "" ); - modInfoStr = "modelId = (" + passedModelInvId + ")"; - } - else if( passedModelName != null && !passedModelName.equals("") ){ - modTopNodeType = getModelVerTopWidgetType( transId, fromAppId,"", "", passedModelName ); - modInfoStr = "modelName = (" + passedModelName + ")"; - } - - if( modTopNodeType.equals("") ){ - if( (passedTopNodeType == null) || passedTopNodeType.equals("") ){ - String msg = "Could not determine the top-node nodeType for this request. modelInfo: [" + modInfoStr + "]"; - throw new AAIException("AAI_6118", msg); - } - else { - // We couldn't find a top-model-type based on passed in model info, but they - // gave us a type to use -- so use it. - modTopNodeType = passedTopNodeType; - } - } - else { - // we did get a topNode type based on model info - make sure it doesn't contradict - // the passsed-in one (if there is one) - if( passedTopNodeType != null && !passedTopNodeType.equals("") - && !passedTopNodeType.equals(modTopNodeType) ){ - throw new AAIException("AAI_6120", "topNodeType passed in [" + passedTopNodeType - + "] does not match nodeType derived for model info passed in: [" - + modTopNodeType + "]"); - } - } - - List<String> modelVersionIds2Check = new ArrayList<>(); - if( (passedModelName != null && !passedModelName.equals("")) ){ - // They passed a modelName, so find all the model UUIDs (model-version-id's) that map to this - modelVersionIds2Check = getModelVerIdsUsingName(transId, fromAppId, passedModelName); - } - if( (passedModelVersionId != null && !passedModelVersionId.equals("")) ){ - // They passed in a modelNameVersionId - if( modelVersionIds2Check.isEmpty() ){ - // There was no modelName passed, so we can use the passed modelNameVersionId - modelVersionIds2Check.add(passedModelVersionId); - } - else if( modelVersionIds2Check.contains(passedModelVersionId) ){ - // The passed in uuid does not conflict with what we got using the passed-in modelName. - // We'll just use the passed in uuid in this case. - // Hopefully they would not be passing strange combinations like this, but we'll try to deal with it. - modelVersionIds2Check = new ArrayList<>(); // Clear out what we had - modelVersionIds2Check.add(passedModelVersionId); - } - } - - // We should now be OK with our topNodeType for this request, so we can look for the actual startNodes - for( int i=0; i < startNodeFilterArrayOfHashes.size(); i++ ){ - // Locate the starting node which will be used to look which corresponds to this set of filter data - Vertex startVtx = null; - try { - Optional<Vertex> result = dbMethHelper.searchVertexByIdentityMap(modTopNodeType, startNodeFilterArrayOfHashes.get(i)); - if (!result.isPresent()) { - throw new AAIException("AAI_6114", "No Node of type " + modTopNodeType + " found for properties"); - } - startVtx = result.get(); - } - catch( AAIException e ){ - String msg = "Could not find startNode of type = [" + modTopNodeType + "], given these params: " - + startNodeFilterArrayOfHashes.get(i) + ". msg # from getUniqueNode() = " + e.getMessage(); - throw new AAIException("AAI_6114", msg); - } - - String vid = startVtx.id().toString(); - String personaModInvId = startVtx.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null); - String personaModVerId = startVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); - - // Either this start-node has persona info (which should not contradict any passed-in model info) - // or they should have passed in the model to use - so we'd just use that. - if( personaModVerId != null && !personaModVerId.equals("") ){ - // There is persona data in this start-node. So make sure it doesn't contradict any "passed" stuff - if( modelVersionIds2Check.isEmpty() - && (passedModelInvId == null || passedModelInvId.equals("")) ){ - // They didn't pass any model info, so use the persona one. - startVertInfo.put(vid, personaModVerId); - } - else if( modelVersionIds2Check.isEmpty() - && (passedModelInvId != null && !passedModelInvId.equals("")) ){ - // They passed in just the modelId - so check it - if( passedModelInvId.equals(personaModInvId) ){ - startVertInfo.put(vid, personaModVerId); - } - } - else if( !modelVersionIds2Check.isEmpty() - && (passedModelInvId == null || passedModelInvId.equals("")) ){ - // They passed in just modelVersionId - so check - if( modelVersionIds2Check.contains(personaModVerId) ){ - startVertInfo.put(vid, personaModVerId); - } - } - else if( !modelVersionIds2Check.isEmpty() - && (passedModelInvId != null && !passedModelInvId.equals("")) ){ - // We have BOTH a modelVersionIds and a modelId to check - if( passedModelInvId.equals(personaModInvId) - && modelVersionIds2Check.contains(personaModVerId) ){ - startVertInfo.put(vid, personaModVerId); - } - } - } - else { - // This start node did not have persona info -- so we will use the passed in model info if they passed one - if( passedModelVersionId!= null && !passedModelVersionId.equals("") ){ - // The model-version-id uniquely identifies a model-ver, so we can use it. - startVertInfo.put(vid, passedModelVersionId); - } - else { - throw new AAIException("AAI_6118", "Found startNode but since it does not have persona data, the " + - " model-version-id is required. "); - } - } - } - } - - return startVertInfo; - - }//end of getStartNodesAndModVersionIds() - - - /** - * Query by model. (really model-ver) - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modelVersionId the model-version-id (unique id in model-ver) - * @param modelInvariantId the model-invariant-id (unique id in model) - * @param modelName the model name - * @param topNodeType - optional (needed if neither model-invariant-id nor model-version-id is passed) - * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used to locate the first node(s) of instance data) - * @param apiVer the api ver - * @return resultSet - * @throws AAIException the AAI exception - */ - public List<ResultSet> queryByModel(String transId, String fromAppId, - String modelVersionId, - String modelInvariantId, - String modelName, - String topNodeType, - List<Map<String,Object>> startNodeFilterArrayOfHashes, - String apiVer ) - throws AAIException { - - final String transId_f = transId; - final String fromAppId_f = fromAppId; - final String modelVersionId_f = modelVersionId; - final String modelInvId_f = modelInvariantId; - final String modelName_f = modelName; - final String topNodeType_f = topNodeType; - final List<Map<String,Object>> startNodeFilterArrayOfHashes_f = startNodeFilterArrayOfHashes; - final String apiVer_f = apiVer; - - // Find out what our time-limit should be - int timeLimitSec = 0; - String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec"); - if( timeLimitString != null && !timeLimitString.equals("") ){ - try { - timeLimitSec = Integer.parseInt(timeLimitString); - } - catch ( Exception nfe ){ - // Don't worry, we will leave the limit as zero - which tells us not to use it. - } - } - - if( timeLimitSec <= 0 ){ - // We will NOT be using a timer - return queryByModel_Timed( transId, fromAppId, - modelVersionId, - modelInvariantId, - modelName, - topNodeType, - startNodeFilterArrayOfHashes, - apiVer ); - } - - List<ResultSet> resultList = new ArrayList<>(); - TimeLimiter limiter = new SimpleTimeLimiter(); - try { - - resultList = limiter.callWithTimeout(new AaiCallable <List<ResultSet>>() { - public List<ResultSet> process() throws AAIException { - return queryByModel_Timed( transId_f, fromAppId_f, - modelVersionId_f, - modelInvId_f, - modelName_f, - topNodeType_f, - startNodeFilterArrayOfHashes_f, - apiVer_f ); - } - }, timeLimitSec, TimeUnit.SECONDS, true); - } - catch (AAIException ae) { - // Re-throw AAIException so we get can tell what happened internally - throw ae; - } - catch (UncheckedTimeoutException ute) { - throw new AAIException("AAI_6140", "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)"); - } - catch (Exception e) { - throw new AAIException("AAI_6128", "Unexpected exception in queryByModel(): " + e.getMessage() ); - } - - return resultList; - } - - - /** - * Query by model (model-ver) timed. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modelVersionId the model-version-id (unique id in model-ver) - * @param modelInvariantId the model-invariant-id (unique id in model) - * @param modelName the model name - * @param topNodeType the top node type - * @param startNodeFilterArrayOfHashesVal the start node filter array of hashes - * @param apiVer the api ver - * @return the array list - * @throws AAIException the AAI exception - */ - public List<ResultSet> queryByModel_Timed(String transId, String fromAppId, - String modelVersionId, - String modelInvariantId, - String modelName, - String topNodeType, - List<Map<String,Object>> startNodeFilterArrayOfHashesVal, - String apiVer ) - throws AAIException { - - List<ResultSet> resultArray = new ArrayList<>(); - - // NOTE: this method can be used for different styles of queries: - // a) They could pass neither a modelVersionId or a modelInvariantId but just pass a set of data defining start-nodes. - // Note - with no model info, we need them to pass the startNodeType for us to be able to use the - // start-node-filter data. We would look at each start node and ensure that each has persona-model info. - // Then use whatever model corresponds to each instance to pull that instance's data. - // b) They could pass a modelInvariantId, but no modelVersionId and no startNode info. In this case, we - // Would look in the database for all nodes that have a model-invariant-id-local that matches what was - // passed, and then for each of those instances, pull the data based on the corresponding model. - // c) They could pass a model-version-id, but no startNode info. We'd make sure that if a - // model-invariant-id was also passed, that it does not conflict - but it really should be null if they - // are passing a full model-version-id. Like case -b-, we'd do a query for all nodes - // that have persona info that corresponds to the model-version-id passed and then - // collect data for each one. - // d) They could pass either modelVersionId or modelInvariantId AND startNodeFilter info. In this case we - // would look at the model info to figure out what the top-node-type is, then look at the - // top-node instances based on the startNodeFilter. We'd only collect data for each instance if - // it's persona model info matches what was passed in. - - - // Sorry to do this, but code that gets called with an empty hash as the first array element was causing errors - List<Map<String,Object>> startNodeFilterArrayOfHashes = new ArrayList <>(); - if( !startNodeFilterArrayOfHashesVal.isEmpty() ){ - Map<String,Object> tmpH = startNodeFilterArrayOfHashesVal.get(0); - if( !tmpH.isEmpty() ){ - for( int i=0; i < startNodeFilterArrayOfHashesVal.size(); i++ ){ - startNodeFilterArrayOfHashes.add( startNodeFilterArrayOfHashesVal.get(i) ); - } - } - } - - // ---------------------------------------------------------------------------------------------------------- - // Get a Hash of all the start-nodes (top instance-data node for a model-ver where we will - // start collecting data) for startNode2ModelVerHash: - // key = vertex-id for the startNode, - // value = model-version-id for the corresponding model-ver - // ---------------------------------------------------------------------------------------------------------- - Map<String, String> startNode2ModelVerHash = getStartNodesAndModVersionIds( transId, fromAppId, - modelVersionId, modelInvariantId, modelName, topNodeType, - startNodeFilterArrayOfHashes, apiVer ); - - //System.out.println("\nDEBUG -- Here's a dump of the startnodes/model-vers: " + startNode2ModelVerHash.toString()); - - // -------------------------------------------------------------------------------------------------------- - // Figure out what-all models (model-ver nodes) we will be dealing with - // Note - Instances must all use the same type of start-node, but do not have to all use the same model-ver. - // -------------------------------------------------------------------------------------------------------- - Map<String, Vertex> distinctModelVersHash = new HashMap<>(); - // For distinctModelVersHash: key = modelVersionId, val= modelVerVertex - String startNodeType = ""; - if( topNodeType != null && !topNodeType.equals("") ){ - startNodeType = topNodeType; - } - - List<String> skipModelVerIdList = new ArrayList<>(); - List<String> skipStartVertVerIdList = new ArrayList<>(); - Set <String> snKeySet = startNode2ModelVerHash.keySet(); - Iterator<String> startNodeIterator = snKeySet.iterator(); - while( startNodeIterator.hasNext() ){ - String modVerIdKey = startNodeIterator.next(); - String modVerId = startNode2ModelVerHash.get(modVerIdKey); - if( !distinctModelVersHash.containsKey(modVerId) ){ - // First time seeing this model-version-id - Vertex modVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", - "model-version-id", modVerId); - String tmpNodeType = ""; - try { - tmpNodeType = getModelVerTopWidgetType( modVerVtx, "" ); - } - catch( AAIException ae ){ - // There must be some old bad data in the db - we will skip over this model-ver since its - // model is not good anymore - but will log that this is happening. - skipModelVerIdList.add(modVerId); - skipStartVertVerIdList.add(modVerIdKey); - System.out.println(">>> WARNING - will not collect model data for this vertex since " + - "it uses an inconsistant model-ver model. Model-version-id = " + modVerId ); - } - - if( tmpNodeType != null && !tmpNodeType.equals("") ){ - if( startNodeType.equals("") ){ - startNodeType = tmpNodeType; - } - else if( !startNodeType.equals(tmpNodeType) ){ - String msg = "Conflict between startNode types for models involved: [" + startNodeType - + "], [" + tmpNodeType + "]"; - throw new AAIException("AAI_6125", msg); - } - distinctModelVersHash.put(modVerId, modVerVtx); - } - } - } - - //System.out.println("\nDEBUG -- Here's a dump of the DISTINCT model-ver hash: " + distinctModelVersHash.toString() ); - - // ------------------------------------------------------------------------------------------------------ - // Get the "valid-next-step" hash for each distinct model-ver - // While we're at it, get a mapping of model-invariant-id|model-version to model-version-id for - // the model-vers being used - // ------------------------------------------------------------------------------------------------------ - Map<String, Multimap<String, String>> validNextStepHash = new HashMap<>(); - // validNextStepHash: key = modelVerId, value = nextStepMap - Set <String> keySet = distinctModelVersHash.keySet(); - Iterator<String> modelVerIterator = keySet.iterator(); - while( modelVerIterator.hasNext() ){ - String modVerKey = modelVerIterator.next(); - if( ! skipModelVerIdList.contains(modVerKey) ){ - Vertex modelVerVtx = distinctModelVersHash.get(modVerKey); - Multimap<String, String> tmpTopoMap = genTopoMap4ModelVer( transId, fromAppId, - modelVerVtx, modVerKey); - validNextStepHash.put(modVerKey, tmpTopoMap); - } - } - - // ------------------------------------------------------------------------------------------------- - // Figure out what the "start-node" for each instance will be (plus the info we will use to - // represent that in our topology) - // ------------------------------------------------------------------------------------------------- - List<String> failedPersonaCheckVids = new ArrayList<>(); - Map<String, String> firstStepInfoHash = new HashMap<>(); - // For firstStepInfoHash: key = startNodeVtxId, val=topNodeType plus personaData if applicable - // ie. the value is what we'd use as the "first-step" for this model. - if( !nodeTypeSupportsPersona( startNodeType) ){ - // This node type doesn't have persona info, so we just use startNodeType for the first-step-info - snKeySet = startNode2ModelVerHash.keySet(); - startNodeIterator = snKeySet.iterator(); - while( startNodeIterator.hasNext() ){ - String vtxKey = startNodeIterator.next(); - firstStepInfoHash.put(vtxKey,startNodeType); - } - } - else { - // Need to check that this node's persona data is good and if it is - use it for the first step info - snKeySet = startNode2ModelVerHash.keySet(); - startNodeIterator = snKeySet.iterator(); - while( startNodeIterator.hasNext() ){ - String vtxKey = startNodeIterator.next(); - Iterator<Vertex> vtxIterator = this.engine.asAdmin().getReadOnlyTraversalSource().V(vtxKey); - Vertex tmpVtx = vtxIterator.next(); - String thisVtxModelVerId = startNode2ModelVerHash.get(vtxKey); - if( skipModelVerIdList.contains(thisVtxModelVerId) ){ - // Skip this vertex because it uses a model-ver that is bad - continue; - } - Vertex modelVerVtx = distinctModelVersHash.get(thisVtxModelVerId); - Vertex modelVtx = getModelGivenModelVer( modelVerVtx, "" ); - String modInvId = modelVtx.<String>property("model-invariant-id").orElse(null); - String personaModInvId = tmpVtx.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null); - String personaModVerId = tmpVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); - if( modInvId.equals(personaModInvId) && thisVtxModelVerId.equals(personaModVerId) ){ - String tmpPersonaInfoStr = startNodeType + "," + personaModInvId + "," + personaModVerId; - firstStepInfoHash.put(vtxKey, tmpPersonaInfoStr ); - } - else { - // we won't use this start node below when we collect data because it should have - // had persona data that matched it's model - but it did not. - failedPersonaCheckVids.add(vtxKey); - } - } - } - - //System.out.println("\nDEBUG -- Here's a dump of the firstStepInfoHash hash: " + firstStepInfoHash.toString() ); - - // ------------------------------------------------------------------------------------------------ - // Loop through each start-node, collect it's data using collectInstanceData() and put the - // resultSet onto the resultArray. - // ------------------------------------------------------------------------------------------------ - - // Make sure they're not bringing back too much data - String maxString = AAIConfig.get("aai.model.query.resultset.maxcount"); - if( maxString != null && !maxString.equals("") ){ - int maxSets = 0; - try { - maxSets = Integer.parseInt(maxString); - } - catch ( Exception nfe ){ - // Don't worry, we will leave the max as zero - which tells us not to use it. - } - - if( maxSets > 0 && (startNode2ModelVerHash.size() > maxSets) ){ - String msg = " Query returns " + startNode2ModelVerHash.size() + " resultSets. Max allowed is: " + maxSets; - throw new AAIException("AAI_6141", msg); - } - } - - snKeySet = startNode2ModelVerHash.keySet(); - startNodeIterator = snKeySet.iterator(); - while( startNodeIterator.hasNext() ){ - String topNodeVtxId = startNodeIterator.next(); - if( failedPersonaCheckVids.contains(topNodeVtxId) || skipStartVertVerIdList.contains(topNodeVtxId) ){ - // Skip this vertex because it failed it's persona-data check above - // Skip this vertex because it uses a model-ver that is bad - continue; - } - - Iterator<Vertex> vtxIterator = this.engine.asAdmin().getReadOnlyTraversalSource().V(topNodeVtxId); - Vertex tmpStartVtx = vtxIterator.next(); - String elementLocationTrail = firstStepInfoHash.get(topNodeVtxId); - String modelVerId = startNode2ModelVerHash.get(topNodeVtxId); - Multimap<String, String> validNextStepMap = validNextStepHash.get(modelVerId); - - List<String> vidsTraversed = new ArrayList<>(); - Map<String,String> emptyDelKeyHash = new HashMap<>(); - Map<String,String> emptyNQElementHash = new HashMap<>(); // Only applies to Named Queries - ResultSet tmpResSet = collectInstanceData( transId, fromAppId, - tmpStartVtx, elementLocationTrail, - validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, emptyNQElementHash, apiVer ); - - resultArray.add(tmpResSet); - } - - return resultArray; - - }// queryByModel_Timed() - - - - /** - * Run delete by model-ver. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modelVersionId the model version id -- unique id for a model-ver node - * @param topNodeTypeVal the top node type val -- required if no model-version-id is passed - * @param startNodeFilterHash the start node filter hash -- used to locate the first node of instance data - * @param apiVer the api ver - * @param resVersion the res version -- resourceVersion of the top/first widget in the model instance - * @return HashMap (keys = vertexIds that were deleted) - * @throws AAIException the AAI exception - */ - public Map<String,String> runDeleteByModel( String transId, String fromAppId, - String modelVersionId, String topNodeTypeVal, Map<String,Object> startNodeFilterHash, String apiVer, String resVersion ) - throws AAIException { - - Map<String,String> retHash = new HashMap<>(); - - // Locate the Model-ver node to be used - Vertex modelVerVtx = null; - if( modelVersionId != null && !modelVersionId.equals("") ){ - modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", - "model-version-id", modelVersionId); - } - else { - // if they didn't pass the modelVersionId, then we need to use the startNode to figure it out - // Locate the starting node based on the start node params - if( topNodeTypeVal == null || topNodeTypeVal.equals("") ){ - throw new AAIException("AAI_6118", "If no model info is passed, then topNodeType is required. "); - } - - Optional<Vertex> result = dbMethHelper.searchVertexByIdentityMap(topNodeTypeVal, startNodeFilterHash); - if (!result.isPresent()) { - throw new AAIException("AAI_6114", "No Node of type " + topNodeTypeVal + " found for properties"); - } - Vertex startVtx = result.get(); - - String startVertModVerId = startVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); - modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", - "model-version-id", startVertModVerId); - } - - if( modelVerVtx == null ){ - throw new AAIException("AAI_6114", "Could not determine the model-ver for the given input parameters. "); - } - - String topNType = "unknown"; - String modelType = getModelTypeFromModelVer( modelVerVtx, "" ); - - if( modelType.equals("widget") ){ - // If they want to delete using a widget-level model.. That is just a delete of the one - // instance of one of our nodes. - String widgModNodeType = modelVerVtx.<String>property("model-name").orElse(null); - if( (widgModNodeType == null) || widgModNodeType.equals("") ){ - String msg = "Could not find model-name for the widget model [" + modelVersionId + "]."; - throw new AAIException("AAI_6132", msg); - } - Optional<Vertex> result = dbMethHelper.locateUniqueVertex(widgModNodeType, startNodeFilterHash); - if (!result.isPresent()) { - throw new AAIException("AAI_6114", "No Node of type " + topNType + " found for properties"); - } - Vertex widgetVtx = result.get(); - String widgId = widgetVtx.id().toString(); - serializer.delete(widgetVtx, resVersion, true); - retHash.put(widgId, widgModNodeType); - return retHash; - } - - // --------------------------------------------------------------------------------- - // If we got to here, this must be either a service or resource model. - // So, we'll need to get a Hash of which parts of the model to delete. - // NOTE- deleteByModel is deleting data based on one specific version of a model. - // --------------------------------------------------------------------------------- - String chkFirstNodePersonaModInvId = ""; - String chkFirstNodePersonaModVerId = ""; - String personaData = ""; - Vertex firstModElementVertex = getTopElementForSvcOrResModelVer( modelVerVtx, "" ); - topNType = getModElementWidgetType( firstModElementVertex, "" ); - if( (topNType == null) || topNType.equals("") ){ - String msg = "Could not determine the top-node nodeType for model-version-id: [" + modelVersionId + "]"; - throw new AAIException("AAI_6132", msg); - } - if( nodeTypeSupportsPersona(topNType) ){ - Vertex modelVtx = getModelGivenModelVer(modelVerVtx,""); - chkFirstNodePersonaModInvId = modelVtx.<String>property("model-invariant-id").orElse(null); - chkFirstNodePersonaModVerId = modelVerVtx.<String>property("model-version-id").orElse(null); - personaData = "," + chkFirstNodePersonaModInvId + "," + chkFirstNodePersonaModVerId; - } - - // Get the deleteKeyHash for this model - String incomingTrail = ""; - Map<String, String> currentHash = new HashMap<>(); - Map<String, Vertex> modConHash = new HashMap<>(); - ArrayList <String> vidsTraversed = new ArrayList<>(); - Map<String, String> delKeyHash = collectDeleteKeyHash( transId, fromAppId, - firstModElementVertex, incomingTrail, currentHash, vidsTraversed, - 0, modConHash, - chkFirstNodePersonaModInvId, chkFirstNodePersonaModVerId ); - - - System.out.println("\n ----DEBUG -----: Delete Hash for model: [" + modelVersionId + "] looks like: "); - for( Map.Entry<String, String> entry : delKeyHash.entrySet() ){ - System.out.println("key = [" + entry.getKey() + "], val = [" + entry.getValue() + "]"); - } - System.out.println("\n -----"); - // Locate the starting node that we'll use to start looking for instance data - Optional<Vertex> result = dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterHash); - if (!result.isPresent()) { - throw new AAIException("AAI_6114", "No Node of type " + topNType + " found for properties"); - } - Vertex startVtx = result.get(); - if( !chkFirstNodePersonaModInvId.equals("") ){ - // NOTE: For Service or Resource models, if this is a nodeType that supports persona's, then - // we need to make sure that the start node matches the persona values. - String startVertPersonaModInvId = startVtx.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null); - String startVertPersonaModVerId = startVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); - if( !chkFirstNodePersonaModInvId.equals(startVertPersonaModInvId) - || !chkFirstNodePersonaModVerId.equals(startVertPersonaModVerId) ){ - String msg = "Persona-Model data mismatch for start node (" + topNType + "), " + - startNodeFilterHash ; - throw new AAIException("AAI_6114", msg); - } - } - String topVid = startVtx.id().toString(); - - // Read the model-ver into a Map for processing - Multimap<String, String> validNextStepMap = genTopoMap4ModelVer(transId, fromAppId, - modelVerVtx, modelVersionId); - - // Collect the data - String elementLocationTrail = topNType + personaData; - vidsTraversed = new ArrayList<>(); - Map<String,String> emptyHash = new HashMap<>(); - - // Pass emptyHash for the NQElement hash since that parameter only applies to Named Queries - ResultSet retResSet = collectInstanceData( transId, fromAppId, - startVtx, elementLocationTrail, - validNextStepMap, vidsTraversed, 0, delKeyHash, emptyHash, apiVer ); - - // Note: the new ResultSet will have each element tagged with the del flag so we'll know if it - // should be deleted or not - so loop through the results in a try-block since some things - // will get auto-deleted by parents before we get to them --- and try to remove each one. - String vidToResCheck = topVid; - - retHash = deleteAsNeededFromResultSet( transId, fromAppId, retResSet, - vidToResCheck, apiVer, resVersion, emptyHash ); - //String msgStr = "processed deletes for these vids: (\n"+ retHash.keySet().toString() + ")."; - - return retHash; - - }// End of runDeleteByModel() - - - - /** - * Delete as needed from result set. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param resSet the res set - * @param vidToResCheck -- this vertex will need to have its resource-version checked - * @param apiVer the api ver - * @param resVersion the res version - * @param hashSoFar the hash so far -- hash of what's been deleted so far - * @return String - * @throws AAIException the AAI exception - */ - public Map<String,String> deleteAsNeededFromResultSet(String transId, String fromAppId, - ResultSet resSet, String vidToResCheck, String apiVer, String resVersion, Map<String,String> hashSoFar ) - throws AAIException - { - Map<String,String> retHash = new HashMap<>(); - retHash.putAll( hashSoFar ); - Boolean deleteIt = false; - - if( resSet.getVert() == null ){ - return retHash; - } - - Vertex thisVtx = resSet.getVert(); - String thisGuyId = ""; - String thisNT = ""; - String thisGuyStr = ""; - - Boolean gotVtxOK = false; - try { - if( thisVtx != null ){ - thisGuyId = thisVtx.id().toString(); - thisNT = thisVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); - thisGuyStr = thisGuyId + "[" + thisNT + " found at:" + resSet.getLocationInModelSubGraph() + "]"; - - // NOTE -- will try to set the NodeType to itself to see if the node has been deleted already in - // this transaction. It lets you get properties from nodes being deleted where the - // delete hasn't been committed yet. This check used to be accomplished with a call to - // "vtx.isRemoved()" but that was a Titan-only feature and is not available anymore since - // we no longer use Titan vertices. - // If we don't do this check, we get errors later when we try to delete the node. - thisVtx.property(AAIProperties.NODE_TYPE, thisNT); - gotVtxOK = true; - } - } - catch (Exception ex) { - // Sometimes things have already been deleted by the time we get to them - just log it. - AAIException aaiException = new AAIException("AAI_6154", thisGuyStr + ". msg = " + ex.getMessage()); - ErrorLogHelper.logException(aaiException); - - } - - if( !gotVtxOK ){ - // The vertex must have already been removed. Just return. - // Note - We need to catch this because the DB sometimes can still have the vtx - // and be able to get its ID but it is flagged internally as removed already. - return retHash; - } - else { - if( resSet.getNewDataDelFlag() != null && resSet.getNewDataDelFlag().equals("T") ){ - logger.debug(">> will try to delete this one >> " + thisGuyStr); - - try { - Boolean requireResourceVersion = false; - if( thisGuyId.equals(vidToResCheck) ){ - // This is the one vertex that we want to check the resourceId before deleting - requireResourceVersion = true; - } - this.serializer.delete(thisVtx, resVersion, requireResourceVersion); - } - catch (AAIException ae) { - String errorCode = ae.getErrorObject().getErrorCode(); - if ( errorCode.equals("6130") || errorCode.equals("6131") ) { - // They didn't pass the correct resource-version for the top node. - throw ae; - } - else { - ErrorLogHelper.logException(ae); - String errText = ae.getErrorObject().getErrorText(); - String errDetail = ae.getMessage(); - logger.debug("Exception when deleting " + thisGuyStr + ". ErrorCode = " + errorCode + - ", errorText = " + errText + ", details = " + errDetail); - } - } - catch( Exception e ){ - // We'd expect to get a "node not found" here sometimes depending on the order that - // the model has us finding / deleting nodes. - // Ignore the exception - but log it so we can see what happened. - AAIException aaiException = new AAIException("AAI_6154", thisGuyStr + ". msg = " + e.getMessage()); - ErrorLogHelper.logException(aaiException); - - } - - // We can't depend on a thrown exception to tell us if a node was deleted since it may - // have been auto=deleted before this removeAaiNode() call. - // --- Not sure if we would want to check anything here -- because the graph.commit() is done outside of this call. - - deleteIt = true; - } - else { - // --- DEBUG ---- - System.out.println(">>>>>>> NOT DELETING THIS ONE >>>> " + thisGuyStr ); - List<String> retArr = dbMethHelper.getVertexProperties(thisVtx); - for( String info : retArr ){ System.out.println(info); } - // --- DEBUG ---- - } - } - - // Now call this routine for the sub-resultSets - List <ResultSet> subResultSetList = resSet.getSubResultSet(); - Iterator <ResultSet> subResSetIter = subResultSetList.iterator(); - while( subResSetIter.hasNext() ){ - ResultSet tmpSubResSet = subResSetIter.next(); - retHash = deleteAsNeededFromResultSet( transId, fromAppId, tmpSubResSet, - vidToResCheck, apiVer, resVersion, retHash ); - } - - if( deleteIt ){ - retHash.put(thisGuyId, thisGuyStr); - } - - return retHash; - - }// deleteAsNeededFromResultSet() - - - - /** - * Query by named query (old version). - * - * @param transId the trans id - * @param fromAppId the from app id - * @param namedQueryUuid the named query uuid - * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data - * @param apiVer the api ver - * @return resultSet - * @throws AAIException the AAI exception - */ - public List<ResultSet> queryByNamedQuery(String transId, String fromAppId, - String namedQueryUuid, - List <Map<String,Object>> startNodeFilterArrayOfHashes, - String apiVer ) - throws AAIException { - - String dummyCutPoint = null; - Map<String,Object> dummySecondaryFilterHash = null; - - return queryByNamedQuery( transId, fromAppId, - namedQueryUuid, - startNodeFilterArrayOfHashes, - apiVer, - dummyCutPoint, - dummySecondaryFilterHash ); - } - - - /** - * Query by named query. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param namedQueryUuid the named query uuid - * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data - * @param apiVer the api ver - * @param secondaryFilterCutPoint nodeType where we will prune if secondary filter is not met - * @param secondaryFilterHash secondary filter params - * @return resultSet - * @throws AAIException the AAI exception - */ - public List<ResultSet> queryByNamedQuery(String transId, String fromAppId, - String namedQueryUuid, - List<Map<String,Object>> startNodeFilterArrayOfHashes, - String apiVer, - String secondaryFilterCutPoint, - Map<String,Object> secondaryFilterHash ) - throws AAIException { - - final String transId_f = transId; - final String fromAppId_f = fromAppId; - final String namedQueryUuid_f = namedQueryUuid; - final List<Map<String,Object>> startNodeFilterArrayOfHashes_f = startNodeFilterArrayOfHashes; - final String apiVer_f = apiVer; - final String secondaryFilterCutPoint_f = secondaryFilterCutPoint; - final Map<String,Object> secondaryFilterHash_f = secondaryFilterHash; - - // Find out what our time-limit should be - int timeLimitSec = 0; - String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec"); - if( timeLimitString != null && !timeLimitString.equals("") ){ - try { - timeLimitSec = Integer.parseInt(timeLimitString); - } - catch ( Exception nfe ){ - // Don't worry, we will leave the limit as zero - which tells us not to use it. - } - } - - if( timeLimitSec <= 0 ){ - // We will NOT be using a timer - return queryByNamedQuery_Timed( transId, fromAppId, - namedQueryUuid, - startNodeFilterArrayOfHashes, - apiVer, - secondaryFilterCutPoint_f, - secondaryFilterHash_f ); - } - - List<ResultSet> resultList = new ArrayList<>(); - TimeLimiter limiter = new SimpleTimeLimiter(); - try { - resultList = limiter.callWithTimeout(new AaiCallable <List<ResultSet>>() { - public List<ResultSet> process() throws AAIException { - return queryByNamedQuery_Timed( transId_f, fromAppId_f, - namedQueryUuid_f, - startNodeFilterArrayOfHashes_f, - apiVer_f, - secondaryFilterCutPoint_f, - secondaryFilterHash_f ); - } - }, timeLimitSec, TimeUnit.SECONDS, true); - - } - catch (AAIException ae) { - // Re-throw AAIException so we get can tell what happened internally - throw ae; - } - catch (UncheckedTimeoutException ute) { - throw new AAIException("AAI_6140", "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)"); - } - catch (Exception e) { - throw new AAIException("AAI_6128", "Unexpected exception in queryByNamedQuery(): " + e.getMessage() ); - } - - return resultList; - } - - - /** - * Query by named query timed. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param namedQueryUuid the named query uuid - * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data - * @param apiVer the api ver - * @param secondaryFilterCutPoint the nodeType where we will parse for the secondary Filter - * @param secondaryFilterHash the secondary filter hash - * @return resultSet - * @throws AAIException the AAI exception - */ - public List<ResultSet> queryByNamedQuery_Timed(String transId, String fromAppId, - String namedQueryUuid, - List<Map<String,Object>> startNodeFilterArrayOfHashes, - String apiVer, - String secondaryFilterCutPoint, - Map<String,Object> secondaryFilterHash - ) - throws AAIException { - - // Locate the Query to be used - Vertex queryVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query", - "named-query-uuid", namedQueryUuid); - - // Get the first/top named-query-element used by this query - Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, queryVtx, "named-query-element"); - Vertex firstNqElementVert = null; - int count = 0; - String topNType = ""; - while( vertI != null && vertI.hasNext() ){ - firstNqElementVert = vertI.next(); - count++; - topNType = getNqElementWidgetType( transId, fromAppId, firstNqElementVert, "" ); - } - - if( count < 1 ){ - // A named query must start with a single top element - throw new AAIException("AAI_6133", "No top-node defined for named-query-uuid = [" + namedQueryUuid + "]"); - } - else if( count > 1 ){ - // A named query should start with a single top element - throw new AAIException("AAI_6133", "More than one top-node defined for named-query-uuid = [" + namedQueryUuid + "]"); - } - if( (topNType == null) || topNType.equals("") ){ - String msg = "Could not determine the top-node nodeType for Named Query: [" + namedQueryUuid + "]"; - throw new AAIException("AAI_6133", msg); - } - - // Read the topology into a hash for processing - Multimap<String, String> validNextStepMap = genTopoMap4NamedQ(transId, fromAppId, queryVtx, namedQueryUuid); - - List<Vertex> startVertList = new ArrayList<>(); - if( startNodeFilterArrayOfHashes.size() == 1 ){ - // If there is only one set of startFilter info given, then allow it to possibly not be - // defining just one start node. - Map<String, Object> tmpHash = startNodeFilterArrayOfHashes.get(0); - Set <String> propKeySet = tmpHash.keySet(); - Iterator<String> propIter = propKeySet.iterator(); - Introspector obj = loader.introspectorFromName(topNType); - Set<String> keys = obj.getKeys(); - boolean foundIndexedField = false; - int propertiesSet = 0; - while( propIter.hasNext() ){ - String oldVtxKey = propIter.next(); - String newKey = oldVtxKey; - String [] parts = oldVtxKey.split("\\."); - if( parts.length == 2 ){ - newKey = parts[1]; - } - Object obVal = tmpHash.get(oldVtxKey); - if (obj.hasProperty(newKey)) { - if (keys.contains(newKey)) { - foundIndexedField = true; - } - obj.setValue(newKey, obVal); - propertiesSet++; - } - } - //we found all the properties in the startNodeType - if (propertiesSet == propKeySet.size()) { - if (foundIndexedField) { - QueryBuilder builder = this.engine.getQueryBuilder().exactMatchQuery(obj); - startVertList = builder.toList(); - } else { - //force a filter from aai-node-type - QueryBuilder builder = this.engine.getQueryBuilder().createContainerQuery(obj).exactMatchQuery(obj); - startVertList = builder.toList(); - } - } else { - Optional<Vertex> tmpVtx = dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterArrayOfHashes.get(0)); - // Only found one, so just use it. - if (tmpVtx.isPresent()) { - startVertList.add(tmpVtx.get()); - } - } - } - else { - // Since they give an array of startNodeFilterHash info, we expect each one - // to just point to one node. - for( int i = 0; i < startNodeFilterArrayOfHashes.size(); i++ ){ - // Locate the starting node for each set of data - Optional<Vertex> tmpVtx = dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterArrayOfHashes.get(i)); - if (tmpVtx.isPresent()) { - startVertList.add(tmpVtx.get()); - } - } - } - - if (startVertList.isEmpty()) { - throw new AAIException("AAI_6114", "No Node of type " + topNType + " found for properties"); - } - // Make sure they're not bringing back too much data - String maxString = AAIConfig.get("aai.model.query.resultset.maxcount"); - if( maxString != null && !maxString.equals("") ){ - int maxSets = Integer.parseInt(maxString); - if( startVertList.size() > maxSets ){ - String msg = " Query returns " + startVertList.size() + " resultSets. Max allowed is: " + maxSets; - throw new AAIException("AAI_6141", msg); - } - } - - // Loop through each start node and get its data - List<ResultSet> resSetList = new ArrayList<>(); - for( int i = 0; i < startVertList.size(); i++ ){ - Vertex startVtx = startVertList.get(i); - // Collect the data - String elementLocationTrail = topNType; - ArrayList <String> vidsTraversed = new ArrayList<>(); - Map<String,String> emptyDelKeyHash = new HashMap<>(); // Does not apply to Named Queries - - // Get the mapping of namedQuery elements to our widget topology for this namedQuery - String incomingTrail = ""; - Map<String, String> currentHash = new HashMap<>(); - - Map<String,String> namedQueryElementHash = collectNQElementHash( transId, fromAppId, - firstNqElementVert, incomingTrail, currentHash, vidsTraversed, 0 ); - - vidsTraversed = new ArrayList<>(); - ResultSet tmpResSet = collectInstanceData( transId, fromAppId, - startVtx, elementLocationTrail, - validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, namedQueryElementHash, apiVer ); - resSetList.add(tmpResSet); - } - - // If a secondary filter was defined, we will prune the collected instance data result set(s) based on it. - List<ResultSet> prunedResSetList = new ArrayList<>(); - if( resSetList != null && !resSetList.isEmpty() ){ - for( int i = 0; i < resSetList.size(); i++ ){ - if( secondaryFilterCutPoint == null || secondaryFilterCutPoint.equals("") || secondaryFilterHash == null ){ - // They didn't want to do any pruning, so just use the results we already had - prunedResSetList.add(resSetList.get(i)); - } - else { - ResultSet tmpResSet = pruneResultSet(resSetList.get(i), secondaryFilterCutPoint, secondaryFilterHash); - if( tmpResSet != null ){ - prunedResSetList.add(tmpResSet); - } - } - } - } - - // Since a NamedQuery can mark some nodes as "do-not-display", we need to collapse our resultSet so - // does not display those nodes. - List<ResultSet> collapsedResSetList = new ArrayList<>(); - if( prunedResSetList != null && !prunedResSetList.isEmpty() ){ - for( int i = 0; i < prunedResSetList.size(); i++ ){ - // Note - a single resultSet could be collapsed into many smaller ones if they - // marked all the "top" node-elements as do-not-output. Ie. the query may - // have had a top-node of "generic-vnf" which joins down to different l-interfaces. - // If they only want to see the l-interfaces, then a single result set - // would be "collapsed" into many separate resultSets - each of which is - // just a single l-interface. - List<ResultSet> tmpResSetList = collapseForDoNotOutput(prunedResSetList.get(i)); - if( tmpResSetList != null && !tmpResSetList.isEmpty() ){ - for( int x = 0; x < tmpResSetList.size(); x++ ){ - //showResultSet( tmpResSetList.get(x), 0 ); //DEBUG-- this was just for testing - collapsedResSetList.add(tmpResSetList.get(x)); - } - } - } - } - - return collapsedResSetList; - - }// End of queryByNamedQuery() - - - /** - * Prune a result set as per a secondary filter. - * - * @param resSetVal the res set val - * @param cutPointType the nodeType where the trim will happen - * @param secFilterHash hash of properties and values to use as the secondary filter - * @return pruned result set - * @throws AAIException the AAI exception - */ - public ResultSet pruneResultSet(ResultSet resSetVal, String cutPointType, Map<String,Object> secFilterHash ) - throws AAIException { - - // Given a ResultSet and some secondary filter info, do pruning as needed - ResultSet pResSet = new ResultSet(); - - // For this ResultSet, we will see if we are on a node of the type that is our cutPoint; - // then only keep it if we peek "below" and see a match for our filter. - - String nt = resSetVal.getVert().<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( nt != null && nt.equals(cutPointType) ){ - // We are on the type of node that may need to be "pruned" along with it's sub-results - if( ! satisfiesFilters(resSetVal, secFilterHash) ){ - // Return an empty result set since we are pruning at this level. - return pResSet; - } - } - - // If we made it to here, we will not be pruning at this level, so we will - // be returning a copy of this resultSet that has it's subResults pruned (as needed). - pResSet.setVert(resSetVal.getVert()); - pResSet.setDoNotOutputFlag(resSetVal.getDoNotOutputFlag()); - pResSet.setExtraPropertyHash(resSetVal.getExtraPropertyHash()); - pResSet.setLocationInModelSubGraph(resSetVal.getLocationInModelSubGraph()); - pResSet.setNewDataDelFlag(resSetVal.getNewDataDelFlag()); - pResSet.setPropertyLimitDesc(resSetVal.getPropertyLimitDesc()); - pResSet.setPropertyOverRideHash(resSetVal.getPropertyOverRideHash()); - - if( !resSetVal.getSubResultSet().isEmpty() ){ - ListIterator<ResultSet> listItr = resSetVal.getSubResultSet().listIterator(); - List<ResultSet> newSubSetList = new ArrayList<>(); - while( listItr.hasNext() ){ - ResultSet tmpSubResSet = pruneResultSet( listItr.next(), cutPointType, secFilterHash ); - if( tmpSubResSet.getVert() != null ){ - // This one wasn't pruned - so keep it. - newSubSetList.add(tmpSubResSet); - } - } - pResSet.setSubResultSet(newSubSetList); - } - - return pResSet; - - }// End pruneResultSet() - - - /** - * Satisfies hash of filters. - * - * @param resSet the res set - * @param filterHash the filter hash - * @return true, if successful - * @throws AAIException the AAI exception - */ - public boolean satisfiesFilters(ResultSet resSet, Map<String,Object> filterHash ) - throws AAIException { - - if( filterHash.isEmpty() ){ - // Nothing to look for, so no, we didn't find it. - return false; - } - - Iterator <?> it = filterHash.entrySet().iterator(); - while( it.hasNext() ){ - Map.Entry<?,?> filtEntry = (Map.Entry<?,?>) it.next(); - String propNodeTypeDotName = (filtEntry.getKey()).toString(); - String fpv = (filtEntry.getValue()).toString(); - - int periodLoc = propNodeTypeDotName.indexOf('.'); - if( periodLoc <= 0 ){ - String emsg = "Bad filter param key passed in: [" + propNodeTypeDotName + "]. Expected format = [nodeName.paramName]\n"; - throw new AAIException("AAI_6120", emsg); - } - else { - String fnt = propNodeTypeDotName.substring(0,periodLoc); - String fpn = propNodeTypeDotName.substring(periodLoc + 1); - if( filterMetByThisSet( resSet, fnt, fpn, fpv ) ){ - //System.out.println(" DEBUG -- satisfied/matched filter: [" + fnt + "|" + fpn + "|" + fpv + "]."); - } - else { - //System.out.println(" DEBUG -- NOT satisfied/matched filter: [" + fnt + "|" + fpn + "|" + fpv + "]."); - return false; - } - } - } - - // Made it through all the filters -- it found what we were looking for. - return true; - - }// end of satisfiesFilters() - - - /** - * Filter met by this set. - * - * @param resSet the res set - * @param filtNodeType the filt node type - * @param filtPropName the filt prop name - * @param filtPropVal the filt prop val - * @return true, if successful - */ - public boolean filterMetByThisSet(ResultSet resSet, String filtNodeType, String filtPropName, String filtPropVal ) { + private static Logger logger = LoggerFactory.getLogger(ModelBasedProcessing.class); + private static final int MAX_LEVELS = 50; // max depth allowed for our model - to protect + // against infinite loop problems + + private TransactionalGraphEngine engine; + private Loader loader; + private DBSerializer serializer; + private DbMethHelper dbMethHelper; + + protected ModelBasedProcessing() { + + } + + public ModelBasedProcessing(Loader loader, TransactionalGraphEngine engine, + DBSerializer serializer) { + this.loader = loader; + this.engine = engine; + this.serializer = serializer; + dbMethHelper = new DbMethHelper(loader, engine); + } + + /** + * Gets the start nodes and model-ver's. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param passedModelVersionId the passed model-version-id -- optional (unique id for a + * model-ver) + * @param passedModelInvId the passed model-invariant-id -- optional + * @param passedModelName the passed model-name -- optional + * @param passedTopNodeType the passed top node type -- optional (needed if neither + * model=invariant-id nor model-version-id is passed) + * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used + * to locate the first node(s) of instance data) + * @param apiVer the api ver + * @return HashMap of startNodes and their corresponding model-version-id's + * @throws AAIException the AAI exception + */ + public Map<String, String> getStartNodesAndModVersionIds(String transId, String fromAppId, + String passedModelVersionId, String passedModelInvId, String passedModelName, + String passedTopNodeType, List<Map<String, Object>> startNodeFilterArrayOfHashes, + String apiVer) throws AAIException { + // ---------------------------------------------------------------------------------------------------- + // Get a hash for all start-nodes (key = vtxId, val = modelVersionId that applies) + // If no start-node-key info is passed, then use either the passed modelVersion or + // the passed model-invariant-id or model-name to collect them. + // If start-node-key info is given, use it instead to look for start-nodes. + // Note: if ONLY start-node-key info is given, then it would have to map to nodes which + // have persona data. Otherwise we'd have no way to know what model to collect data with. + // ---------------------------------------------------------------------------------------------------- + + Iterator<Vertex> startVerts = null; + Map<String, String> startVertInfo = new HashMap<>(); + + if (startNodeFilterArrayOfHashes.isEmpty()) { + // Since they did not give any data to find start instances, we will have to find them + // using whatever model-info they provided so we can use it to map to persona-data in + // the db. + if ((passedModelVersionId == null || passedModelVersionId.equals("")) + && (passedModelInvId == null || passedModelInvId.equals("")) + && (passedModelName == null || passedModelName.equals(""))) { + throw new AAIException("AAI_6118", + "ModelInvariantId or ModelName or ModelVersionId required if no startNodeFilter data passed."); + } else { + // Use whatever model info they pass to find start-node instances + // Get the first/top named-query-element used by this query + if (passedModelVersionId != null && !passedModelVersionId.equals("")) { + // Need to look up the model-invariant-id and model-version to check against + // persona data + Vertex modVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", + "model-version-id", passedModelVersionId); + Vertex modVtx = getModelGivenModelVer(modVerVtx, ""); + String calcModId = modVtx.<String>property("model-invariant-id").orElse(null); + // Now we can look up instances that match this model's info + if (calcModId != null) { + startVerts = this.engine.asAdmin().getReadOnlyTraversalSource().V() + .has(addDBAliasedSuffix("model-invariant-id"), calcModId) + .has(addDBAliasedSuffix("model-version-id"), passedModelVersionId); + } + } else if (passedModelInvId != null && !passedModelInvId.equals("")) { + // They gave us the model-invariant-id + startVerts = this.engine.asAdmin().getReadOnlyTraversalSource().V() + .has(addDBAliasedSuffix("model-invariant-id"), passedModelInvId); + } else if (passedModelName != null && !passedModelName.equals("")) { + List<Vertex> modelVerVtxList = + getModelVersUsingName(transId, fromAppId, passedModelName); + List<Vertex> startVtxList = new ArrayList<>(); + // Need to look up the model-inv-ids and model-versions to check against persona + // data + if (!modelVerVtxList.isEmpty()) { + for (int i = 0; i < modelVerVtxList.size(); i++) { + String calcModVerId = (modelVerVtxList.get(i)) + .<String>property("model-version-id").orElse(null); + Vertex modVtx = getModelGivenModelVer(modelVerVtxList.get(i), ""); + String calcModInvId = + modVtx.<String>property("model-invariant-id").orElse(null); + // Now we can look up instances that match this model's info + Iterator<Vertex> tmpStartIter = + this.engine.asAdmin().getReadOnlyTraversalSource().V() + .has(addDBAliasedSuffix("model-invariant-id"), calcModInvId) + .has(addDBAliasedSuffix("model-version-id"), calcModVerId); + while (tmpStartIter.hasNext()) { + Vertex tmpStartVert = tmpStartIter.next(); + startVtxList.add(tmpStartVert); + } + } + } + if (!startVtxList.isEmpty()) { + startVerts = startVtxList.iterator(); + } + } + } + + if (startVerts != null) { + while (startVerts.hasNext()) { + Vertex tmpStartVert = startVerts.next(); + String vid = tmpStartVert.id().toString(); + // String tmpModId = + // tmpStartVert.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null); + String tmpModVerId = tmpStartVert + .<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); + startVertInfo.put(vid, tmpModVerId); + } + } + if (startVertInfo.isEmpty()) { + throw new AAIException("AAI_6114", + "Start Node(s) could not be found for model data passed. " + + "(modelVersionId = [" + passedModelVersionId + "], modelInvariantId = [" + + passedModelInvId + "], modelName = [" + passedModelName + "])"); + } + + return startVertInfo; + } else { + // Use start-node filter info to find start-node(s) - Note - there could also be model + // info passed that we'll need + // to use to trim down the set of start-nodes that we find based on the startNodeFilter + // data. + String modTopNodeType = ""; + String modInfoStr = ""; + if (passedModelVersionId != null && !passedModelVersionId.equals("")) { + modTopNodeType = + getModelVerTopWidgetType(transId, fromAppId, passedModelVersionId, "", ""); + modInfoStr = "modelVersionId = (" + passedModelVersionId + ")"; + } else if (passedModelInvId != null && !passedModelInvId.equals("")) { + modTopNodeType = + getModelVerTopWidgetType(transId, fromAppId, "", passedModelInvId, ""); + modInfoStr = "modelId = (" + passedModelInvId + ")"; + } else if (passedModelName != null && !passedModelName.equals("")) { + modTopNodeType = + getModelVerTopWidgetType(transId, fromAppId, "", "", passedModelName); + modInfoStr = "modelName = (" + passedModelName + ")"; + } + + if (modTopNodeType.equals("")) { + if ((passedTopNodeType == null) || passedTopNodeType.equals("")) { + String msg = + "Could not determine the top-node nodeType for this request. modelInfo: [" + + modInfoStr + "]"; + throw new AAIException("AAI_6118", msg); + } else { + // We couldn't find a top-model-type based on passed in model info, but they + // gave us a type to use -- so use it. + modTopNodeType = passedTopNodeType; + } + } else { + // we did get a topNode type based on model info - make sure it doesn't contradict + // the passsed-in one (if there is one) + if (passedTopNodeType != null && !passedTopNodeType.equals("") + && !passedTopNodeType.equals(modTopNodeType)) { + throw new AAIException("AAI_6120", + "topNodeType passed in [" + passedTopNodeType + + "] does not match nodeType derived for model info passed in: [" + + modTopNodeType + "]"); + } + } + + List<String> modelVersionIds2Check = new ArrayList<>(); + if ((passedModelName != null && !passedModelName.equals(""))) { + // They passed a modelName, so find all the model UUIDs (model-version-id's) that + // map to this + modelVersionIds2Check = + getModelVerIdsUsingName(transId, fromAppId, passedModelName); + } + if ((passedModelVersionId != null && !passedModelVersionId.equals(""))) { + // They passed in a modelNameVersionId + if (modelVersionIds2Check.isEmpty()) { + // There was no modelName passed, so we can use the passed modelNameVersionId + modelVersionIds2Check.add(passedModelVersionId); + } else if (modelVersionIds2Check.contains(passedModelVersionId)) { + // The passed in uuid does not conflict with what we got using the passed-in + // modelName. + // We'll just use the passed in uuid in this case. + // Hopefully they would not be passing strange combinations like this, but we'll + // try to deal with it. + modelVersionIds2Check = new ArrayList<>(); // Clear out what we had + modelVersionIds2Check.add(passedModelVersionId); + } + } + + // We should now be OK with our topNodeType for this request, so we can look for the + // actual startNodes + for (int i = 0; i < startNodeFilterArrayOfHashes.size(); i++) { + // Locate the starting node which will be used to look which corresponds to this set + // of filter data + Vertex startVtx = null; + try { + Optional<Vertex> result = dbMethHelper.searchVertexByIdentityMap(modTopNodeType, + startNodeFilterArrayOfHashes.get(i)); + if (!result.isPresent()) { + throw new AAIException("AAI_6114", + "No Node of type " + modTopNodeType + " found for properties"); + } + startVtx = result.get(); + } catch (AAIException e) { + String msg = "Could not find startNode of type = [" + modTopNodeType + + "], given these params: " + startNodeFilterArrayOfHashes.get(i) + + ". msg # from getUniqueNode() = " + e.getMessage(); + throw new AAIException("AAI_6114", msg); + } + + String vid = startVtx.id().toString(); + String personaModInvId = startVtx + .<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null); + String personaModVerId = + startVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); + + // Either this start-node has persona info (which should not contradict any + // passed-in model info) + // or they should have passed in the model to use - so we'd just use that. + if (personaModVerId != null && !personaModVerId.equals("")) { + // There is persona data in this start-node. So make sure it doesn't contradict + // any "passed" stuff + if (modelVersionIds2Check.isEmpty() + && (passedModelInvId == null || passedModelInvId.equals(""))) { + // They didn't pass any model info, so use the persona one. + startVertInfo.put(vid, personaModVerId); + } else if (modelVersionIds2Check.isEmpty() + && (passedModelInvId != null && !passedModelInvId.equals(""))) { + // They passed in just the modelId - so check it + if (passedModelInvId.equals(personaModInvId)) { + startVertInfo.put(vid, personaModVerId); + } + } else if (!modelVersionIds2Check.isEmpty() + && (passedModelInvId == null || passedModelInvId.equals(""))) { + // They passed in just modelVersionId - so check + if (modelVersionIds2Check.contains(personaModVerId)) { + startVertInfo.put(vid, personaModVerId); + } + } else if (!modelVersionIds2Check.isEmpty() + && (passedModelInvId != null && !passedModelInvId.equals(""))) { + // We have BOTH a modelVersionIds and a modelId to check + if (passedModelInvId.equals(personaModInvId) + && modelVersionIds2Check.contains(personaModVerId)) { + startVertInfo.put(vid, personaModVerId); + } + } + } else { + // This start node did not have persona info -- so we will use the passed in + // model info if they passed one + if (passedModelVersionId != null && !passedModelVersionId.equals("")) { + // The model-version-id uniquely identifies a model-ver, so we can use it. + startVertInfo.put(vid, passedModelVersionId); + } else { + throw new AAIException("AAI_6118", + "Found startNode but since it does not have persona data, the " + + " model-version-id is required. "); + } + } + } + } + + return startVertInfo; + + }// end of getStartNodesAndModVersionIds() + + /** + * Query by model. (really model-ver) + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVersionId the model-version-id (unique id in model-ver) + * @param modelInvariantId the model-invariant-id (unique id in model) + * @param modelName the model name + * @param topNodeType - optional (needed if neither model-invariant-id nor model-version-id is + * passed) + * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used + * to locate the first node(s) of instance data) + * @param apiVer the api ver + * @return resultSet + * @throws AAIException the AAI exception + */ + public List<ResultSet> queryByModel(String transId, String fromAppId, String modelVersionId, + String modelInvariantId, String modelName, String topNodeType, + List<Map<String, Object>> startNodeFilterArrayOfHashes, String apiVer) throws AAIException { + + final String transId_f = transId; + final String fromAppId_f = fromAppId; + final String modelVersionId_f = modelVersionId; + final String modelInvId_f = modelInvariantId; + final String modelName_f = modelName; + final String topNodeType_f = topNodeType; + final List<Map<String, Object>> startNodeFilterArrayOfHashes_f = + startNodeFilterArrayOfHashes; + final String apiVer_f = apiVer; + + // Find out what our time-limit should be + int timeLimitSec = 0; + String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec"); + if (timeLimitString != null && !timeLimitString.equals("")) { + try { + timeLimitSec = Integer.parseInt(timeLimitString); + } catch (Exception nfe) { + // Don't worry, we will leave the limit as zero - which tells us not to use it. + } + } + + if (timeLimitSec <= 0) { + // We will NOT be using a timer + return queryByModel_Timed(transId, fromAppId, modelVersionId, modelInvariantId, + modelName, topNodeType, startNodeFilterArrayOfHashes, apiVer); + } + + List<ResultSet> resultList = new ArrayList<>(); + TimeLimiter limiter = new SimpleTimeLimiter(); + try { + + resultList = limiter.callWithTimeout(new AaiCallable<List<ResultSet>>() { + public List<ResultSet> process() throws AAIException { + return queryByModel_Timed(transId_f, fromAppId_f, modelVersionId_f, + modelInvId_f, modelName_f, topNodeType_f, startNodeFilterArrayOfHashes_f, + apiVer_f); + } + }, timeLimitSec, TimeUnit.SECONDS, true); + } catch (AAIException ae) { + // Re-throw AAIException so we get can tell what happened internally + throw ae; + } catch (UncheckedTimeoutException ute) { + throw new AAIException("AAI_6140", + "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)"); + } catch (Exception e) { + throw new AAIException("AAI_6128", + "Unexpected exception in queryByModel(): " + e.getMessage()); + } + + return resultList; + } + + /** + * Query by model (model-ver) timed. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVersionId the model-version-id (unique id in model-ver) + * @param modelInvariantId the model-invariant-id (unique id in model) + * @param modelName the model name + * @param topNodeType the top node type + * @param startNodeFilterArrayOfHashesVal the start node filter array of hashes + * @param apiVer the api ver + * @return the array list + * @throws AAIException the AAI exception + */ + public List<ResultSet> queryByModel_Timed(String transId, String fromAppId, + String modelVersionId, String modelInvariantId, String modelName, String topNodeType, + List<Map<String, Object>> startNodeFilterArrayOfHashesVal, String apiVer) + throws AAIException { + + List<ResultSet> resultArray = new ArrayList<>(); + + // NOTE: this method can be used for different styles of queries: + // a) They could pass neither a modelVersionId or a modelInvariantId but just pass a set of + // data defining start-nodes. + // Note - with no model info, we need them to pass the startNodeType for us to be able to + // use the + // start-node-filter data. We would look at each start node and ensure that each has + // persona-model info. + // Then use whatever model corresponds to each instance to pull that instance's data. + // b) They could pass a modelInvariantId, but no modelVersionId and no startNode info. In + // this case, we + // Would look in the database for all nodes that have a model-invariant-id-local that + // matches what was + // passed, and then for each of those instances, pull the data based on the corresponding + // model. + // c) They could pass a model-version-id, but no startNode info. We'd make sure that if a + // model-invariant-id was also passed, that it does not conflict - but it really should be + // null if they + // are passing a full model-version-id. Like case -b-, we'd do a query for all nodes + // that have persona info that corresponds to the model-version-id passed and then + // collect data for each one. + // d) They could pass either modelVersionId or modelInvariantId AND startNodeFilter info. In + // this case we + // would look at the model info to figure out what the top-node-type is, then look at the + // top-node instances based on the startNodeFilter. We'd only collect data for each instance + // if + // it's persona model info matches what was passed in. + + // Sorry to do this, but code that gets called with an empty hash as the first array element + // was causing errors + List<Map<String, Object>> startNodeFilterArrayOfHashes = new ArrayList<>(); + if (!startNodeFilterArrayOfHashesVal.isEmpty()) { + Map<String, Object> tmpH = startNodeFilterArrayOfHashesVal.get(0); + if (!tmpH.isEmpty()) { + for (int i = 0; i < startNodeFilterArrayOfHashesVal.size(); i++) { + startNodeFilterArrayOfHashes.add(startNodeFilterArrayOfHashesVal.get(i)); + } + } + } + + // ---------------------------------------------------------------------------------------------------------- + // Get a Hash of all the start-nodes (top instance-data node for a model-ver where we will + // start collecting data) for startNode2ModelVerHash: + // key = vertex-id for the startNode, + // value = model-version-id for the corresponding model-ver + // ---------------------------------------------------------------------------------------------------------- + Map<String, String> startNode2ModelVerHash = + getStartNodesAndModVersionIds(transId, fromAppId, modelVersionId, modelInvariantId, + modelName, topNodeType, startNodeFilterArrayOfHashes, apiVer); + + // System.out.println("\nDEBUG -- Here's a dump of the startnodes/model-vers: " + + // startNode2ModelVerHash.toString()); + + // -------------------------------------------------------------------------------------------------------- + // Figure out what-all models (model-ver nodes) we will be dealing with + // Note - Instances must all use the same type of start-node, but do not have to all use the + // same model-ver. + // -------------------------------------------------------------------------------------------------------- + Map<String, Vertex> distinctModelVersHash = new HashMap<>(); + // For distinctModelVersHash: key = modelVersionId, val= modelVerVertex + String startNodeType = ""; + if (topNodeType != null && !topNodeType.equals("")) { + startNodeType = topNodeType; + } + + List<String> skipModelVerIdList = new ArrayList<>(); + List<String> skipStartVertVerIdList = new ArrayList<>(); + Set<String> snKeySet = startNode2ModelVerHash.keySet(); + Iterator<String> startNodeIterator = snKeySet.iterator(); + while (startNodeIterator.hasNext()) { + String modVerIdKey = startNodeIterator.next(); + String modVerId = startNode2ModelVerHash.get(modVerIdKey); + if (!distinctModelVersHash.containsKey(modVerId)) { + // First time seeing this model-version-id + Vertex modVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", + "model-version-id", modVerId); + String tmpNodeType = ""; + try { + tmpNodeType = getModelVerTopWidgetType(modVerVtx, ""); + } catch (AAIException ae) { + // There must be some old bad data in the db - we will skip over this model-ver + // since its + // model is not good anymore - but will log that this is happening. + skipModelVerIdList.add(modVerId); + skipStartVertVerIdList.add(modVerIdKey); + System.out + .println(">>> WARNING - will not collect model data for this vertex since " + + "it uses an inconsistant model-ver model. Model-version-id = " + + modVerId); + } + + if (tmpNodeType != null && !tmpNodeType.equals("")) { + if (startNodeType.equals("")) { + startNodeType = tmpNodeType; + } else if (!startNodeType.equals(tmpNodeType)) { + String msg = "Conflict between startNode types for models involved: [" + + startNodeType + "], [" + tmpNodeType + "]"; + throw new AAIException("AAI_6125", msg); + } + distinctModelVersHash.put(modVerId, modVerVtx); + } + } + } + + // System.out.println("\nDEBUG -- Here's a dump of the DISTINCT model-ver hash: " + + // distinctModelVersHash.toString() ); + + // ------------------------------------------------------------------------------------------------------ + // Get the "valid-next-step" hash for each distinct model-ver + // While we're at it, get a mapping of model-invariant-id|model-version to model-version-id + // for + // the model-vers being used + // ------------------------------------------------------------------------------------------------------ + Map<String, Multimap<String, String>> validNextStepHash = new HashMap<>(); + // validNextStepHash: key = modelVerId, value = nextStepMap + Set<String> keySet = distinctModelVersHash.keySet(); + Iterator<String> modelVerIterator = keySet.iterator(); + while (modelVerIterator.hasNext()) { + String modVerKey = modelVerIterator.next(); + if (!skipModelVerIdList.contains(modVerKey)) { + Vertex modelVerVtx = distinctModelVersHash.get(modVerKey); + Multimap<String, String> tmpTopoMap = + genTopoMap4ModelVer(transId, fromAppId, modelVerVtx, modVerKey); + validNextStepHash.put(modVerKey, tmpTopoMap); + } + } + + // ------------------------------------------------------------------------------------------------- + // Figure out what the "start-node" for each instance will be (plus the info we will use to + // represent that in our topology) + // ------------------------------------------------------------------------------------------------- + List<String> failedPersonaCheckVids = new ArrayList<>(); + Map<String, String> firstStepInfoHash = new HashMap<>(); + // For firstStepInfoHash: key = startNodeVtxId, val=topNodeType plus personaData if + // applicable + // ie. the value is what we'd use as the "first-step" for this model. + if (!nodeTypeSupportsPersona(startNodeType)) { + // This node type doesn't have persona info, so we just use startNodeType for the + // first-step-info + snKeySet = startNode2ModelVerHash.keySet(); + startNodeIterator = snKeySet.iterator(); + while (startNodeIterator.hasNext()) { + String vtxKey = startNodeIterator.next(); + firstStepInfoHash.put(vtxKey, startNodeType); + } + } else { + // Need to check that this node's persona data is good and if it is - use it for the + // first step info + snKeySet = startNode2ModelVerHash.keySet(); + startNodeIterator = snKeySet.iterator(); + while (startNodeIterator.hasNext()) { + String vtxKey = startNodeIterator.next(); + Iterator<Vertex> vtxIterator = + this.engine.asAdmin().getReadOnlyTraversalSource().V(vtxKey); + Vertex tmpVtx = vtxIterator.next(); + String thisVtxModelVerId = startNode2ModelVerHash.get(vtxKey); + if (skipModelVerIdList.contains(thisVtxModelVerId)) { + // Skip this vertex because it uses a model-ver that is bad + continue; + } + Vertex modelVerVtx = distinctModelVersHash.get(thisVtxModelVerId); + Vertex modelVtx = getModelGivenModelVer(modelVerVtx, ""); + String modInvId = modelVtx.<String>property("model-invariant-id").orElse(null); + String personaModInvId = + tmpVtx.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null); + String personaModVerId = + tmpVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); + if (modInvId.equals(personaModInvId) && thisVtxModelVerId.equals(personaModVerId)) { + String tmpPersonaInfoStr = + startNodeType + "," + personaModInvId + "," + personaModVerId; + firstStepInfoHash.put(vtxKey, tmpPersonaInfoStr); + } else { + // we won't use this start node below when we collect data because it should + // have + // had persona data that matched it's model - but it did not. + failedPersonaCheckVids.add(vtxKey); + } + } + } + + // System.out.println("\nDEBUG -- Here's a dump of the firstStepInfoHash hash: " + + // firstStepInfoHash.toString() ); + + // ------------------------------------------------------------------------------------------------ + // Loop through each start-node, collect it's data using collectInstanceData() and put the + // resultSet onto the resultArray. + // ------------------------------------------------------------------------------------------------ + + // Make sure they're not bringing back too much data + String maxString = AAIConfig.get("aai.model.query.resultset.maxcount"); + if (maxString != null && !maxString.equals("")) { + int maxSets = 0; + try { + maxSets = Integer.parseInt(maxString); + } catch (Exception nfe) { + // Don't worry, we will leave the max as zero - which tells us not to use it. + } + + if (maxSets > 0 && (startNode2ModelVerHash.size() > maxSets)) { + String msg = " Query returns " + startNode2ModelVerHash.size() + + " resultSets. Max allowed is: " + maxSets; + throw new AAIException("AAI_6141", msg); + } + } + + snKeySet = startNode2ModelVerHash.keySet(); + startNodeIterator = snKeySet.iterator(); + while (startNodeIterator.hasNext()) { + String topNodeVtxId = startNodeIterator.next(); + if (failedPersonaCheckVids.contains(topNodeVtxId) + || skipStartVertVerIdList.contains(topNodeVtxId)) { + // Skip this vertex because it failed it's persona-data check above + // Skip this vertex because it uses a model-ver that is bad + continue; + } + + Iterator<Vertex> vtxIterator = + this.engine.asAdmin().getReadOnlyTraversalSource().V(topNodeVtxId); + Vertex tmpStartVtx = vtxIterator.next(); + String elementLocationTrail = firstStepInfoHash.get(topNodeVtxId); + String modelVerId = startNode2ModelVerHash.get(topNodeVtxId); + Multimap<String, String> validNextStepMap = validNextStepHash.get(modelVerId); + + List<String> vidsTraversed = new ArrayList<>(); + Map<String, String> emptyDelKeyHash = new HashMap<>(); + Map<String, String> emptyNQElementHash = new HashMap<>(); // Only applies to Named + // Queries + ResultSet tmpResSet = collectInstanceData(transId, fromAppId, tmpStartVtx, + elementLocationTrail, validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, + emptyNQElementHash, apiVer); + + resultArray.add(tmpResSet); + } + + return resultArray; + + }// queryByModel_Timed() + + /** + * Run delete by model-ver. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVersionId the model version id -- unique id for a model-ver node + * @param topNodeTypeVal the top node type val -- required if no model-version-id is passed + * @param startNodeFilterHash the start node filter hash -- used to locate the first node of + * instance data + * @param apiVer the api ver + * @param resVersion the res version -- resourceVersion of the top/first widget in the model + * instance + * @return HashMap (keys = vertexIds that were deleted) + * @throws AAIException the AAI exception + */ + public Map<String, String> runDeleteByModel(String transId, String fromAppId, + String modelVersionId, String topNodeTypeVal, Map<String, Object> startNodeFilterHash, + String apiVer, String resVersion) throws AAIException { + + Map<String, String> retHash = new HashMap<>(); + + // Locate the Model-ver node to be used + Vertex modelVerVtx = null; + if (modelVersionId != null && !modelVersionId.equals("")) { + modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", "model-version-id", + modelVersionId); + } else { + // if they didn't pass the modelVersionId, then we need to use the startNode to figure + // it out + // Locate the starting node based on the start node params + if (topNodeTypeVal == null || topNodeTypeVal.equals("")) { + throw new AAIException("AAI_6118", + "If no model info is passed, then topNodeType is required. "); + } + + Optional<Vertex> result = + dbMethHelper.searchVertexByIdentityMap(topNodeTypeVal, startNodeFilterHash); + if (!result.isPresent()) { + throw new AAIException("AAI_6114", + "No Node of type " + topNodeTypeVal + " found for properties"); + } + Vertex startVtx = result.get(); + + String startVertModVerId = + startVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); + modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", "model-version-id", + startVertModVerId); + } + + if (modelVerVtx == null) { + throw new AAIException("AAI_6114", + "Could not determine the model-ver for the given input parameters. "); + } + + String topNType = "unknown"; + String modelType = getModelTypeFromModelVer(modelVerVtx, ""); + + if (modelType.equals("widget")) { + // If they want to delete using a widget-level model.. That is just a delete of the one + // instance of one of our nodes. + String widgModNodeType = modelVerVtx.<String>property("model-name").orElse(null); + if ((widgModNodeType == null) || widgModNodeType.equals("")) { + String msg = + "Could not find model-name for the widget model [" + modelVersionId + "]."; + throw new AAIException("AAI_6132", msg); + } + Optional<Vertex> result = + dbMethHelper.locateUniqueVertex(widgModNodeType, startNodeFilterHash); + if (!result.isPresent()) { + throw new AAIException("AAI_6114", + "No Node of type " + topNType + " found for properties"); + } + Vertex widgetVtx = result.get(); + String widgId = widgetVtx.id().toString(); + serializer.delete(widgetVtx, resVersion, true); + retHash.put(widgId, widgModNodeType); + return retHash; + } + + // --------------------------------------------------------------------------------- + // If we got to here, this must be either a service or resource model. + // So, we'll need to get a Hash of which parts of the model to delete. + // NOTE- deleteByModel is deleting data based on one specific version of a model. + // --------------------------------------------------------------------------------- + String chkFirstNodePersonaModInvId = ""; + String chkFirstNodePersonaModVerId = ""; + String personaData = ""; + Vertex firstModElementVertex = getTopElementForSvcOrResModelVer(modelVerVtx, ""); + topNType = getModElementWidgetType(firstModElementVertex, ""); + if ((topNType == null) || topNType.equals("")) { + String msg = "Could not determine the top-node nodeType for model-version-id: [" + + modelVersionId + "]"; + throw new AAIException("AAI_6132", msg); + } + if (nodeTypeSupportsPersona(topNType)) { + Vertex modelVtx = getModelGivenModelVer(modelVerVtx, ""); + chkFirstNodePersonaModInvId = + modelVtx.<String>property("model-invariant-id").orElse(null); + chkFirstNodePersonaModVerId = + modelVerVtx.<String>property("model-version-id").orElse(null); + personaData = "," + chkFirstNodePersonaModInvId + "," + chkFirstNodePersonaModVerId; + } + + // Get the deleteKeyHash for this model + String incomingTrail = ""; + Map<String, String> currentHash = new HashMap<>(); + Map<String, Vertex> modConHash = new HashMap<>(); + ArrayList<String> vidsTraversed = new ArrayList<>(); + Map<String, String> delKeyHash = collectDeleteKeyHash(transId, fromAppId, + firstModElementVertex, incomingTrail, currentHash, vidsTraversed, 0, modConHash, + chkFirstNodePersonaModInvId, chkFirstNodePersonaModVerId); + + System.out.println( + "\n ----DEBUG -----: Delete Hash for model: [" + modelVersionId + "] looks like: "); + for (Map.Entry<String, String> entry : delKeyHash.entrySet()) { + System.out.println("key = [" + entry.getKey() + "], val = [" + entry.getValue() + "]"); + } + System.out.println("\n -----"); + // Locate the starting node that we'll use to start looking for instance data + Optional<Vertex> result = + dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterHash); + if (!result.isPresent()) { + throw new AAIException("AAI_6114", + "No Node of type " + topNType + " found for properties"); + } + Vertex startVtx = result.get(); + if (!chkFirstNodePersonaModInvId.equals("")) { + // NOTE: For Service or Resource models, if this is a nodeType that supports persona's, + // then + // we need to make sure that the start node matches the persona values. + String startVertPersonaModInvId = + startVtx.<String>property(addDBAliasedSuffix("model-invariant-id")).orElse(null); + String startVertPersonaModVerId = + startVtx.<String>property(addDBAliasedSuffix("model-version-id")).orElse(null); + if (!chkFirstNodePersonaModInvId.equals(startVertPersonaModInvId) + || !chkFirstNodePersonaModVerId.equals(startVertPersonaModVerId)) { + String msg = "Persona-Model data mismatch for start node (" + topNType + "), " + + startNodeFilterHash; + throw new AAIException("AAI_6114", msg); + } + } + String topVid = startVtx.id().toString(); + + // Read the model-ver into a Map for processing + Multimap<String, String> validNextStepMap = + genTopoMap4ModelVer(transId, fromAppId, modelVerVtx, modelVersionId); + + // Collect the data + String elementLocationTrail = topNType + personaData; + vidsTraversed = new ArrayList<>(); + Map<String, String> emptyHash = new HashMap<>(); + + // Pass emptyHash for the NQElement hash since that parameter only applies to Named Queries + ResultSet retResSet = + collectInstanceData(transId, fromAppId, startVtx, elementLocationTrail, + validNextStepMap, vidsTraversed, 0, delKeyHash, emptyHash, apiVer); + + // Note: the new ResultSet will have each element tagged with the del flag so we'll know if + // it + // should be deleted or not - so loop through the results in a try-block since some things + // will get auto-deleted by parents before we get to them --- and try to remove each one. + String vidToResCheck = topVid; + + retHash = deleteAsNeededFromResultSet(transId, fromAppId, retResSet, vidToResCheck, apiVer, + resVersion, emptyHash); + // String msgStr = "processed deletes for these vids: (\n"+ retHash.keySet().toString() + + // ")."; + + return retHash; + + }// End of runDeleteByModel() + + /** + * Delete as needed from result set. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param resSet the res set + * @param vidToResCheck -- this vertex will need to have its resource-version checked + * @param apiVer the api ver + * @param resVersion the res version + * @param hashSoFar the hash so far -- hash of what's been deleted so far + * @return String + * @throws AAIException the AAI exception + */ + public Map<String, String> deleteAsNeededFromResultSet(String transId, String fromAppId, + ResultSet resSet, String vidToResCheck, String apiVer, String resVersion, + Map<String, String> hashSoFar) throws AAIException { + Map<String, String> retHash = new HashMap<>(); + retHash.putAll(hashSoFar); + Boolean deleteIt = false; + + if (resSet.getVert() == null) { + return retHash; + } + + Vertex thisVtx = resSet.getVert(); + String thisGuyId = ""; + String thisNT = ""; + String thisGuyStr = ""; + + Boolean gotVtxOK = false; + try { + if (thisVtx != null) { + thisGuyId = thisVtx.id().toString(); + thisNT = thisVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); + thisGuyStr = thisGuyId + "[" + thisNT + " found at:" + + resSet.getLocationInModelSubGraph() + "]"; + + // NOTE -- will try to set the NodeType to itself to see if the node has been + // deleted already in + // this transaction. It lets you get properties from nodes being deleted where the + // delete hasn't been committed yet. This check used to be accomplished with a call + // to + // "vtx.isRemoved()" but that was a Titan-only feature and is not available anymore + // since + // we no longer use Titan vertices. + // If we don't do this check, we get errors later when we try to delete the node. + thisVtx.property(AAIProperties.NODE_TYPE, thisNT); + gotVtxOK = true; + } + } catch (Exception ex) { + // Sometimes things have already been deleted by the time we get to them - just log it. + AAIException aaiException = + new AAIException("AAI_6154", thisGuyStr + ". msg = " + ex.getMessage()); + ErrorLogHelper.logException(aaiException); + + } + + if (!gotVtxOK) { + // The vertex must have already been removed. Just return. + // Note - We need to catch this because the DB sometimes can still have the vtx + // and be able to get its ID but it is flagged internally as removed already. + return retHash; + } else { + if (resSet.getNewDataDelFlag() != null && resSet.getNewDataDelFlag().equals("T")) { + logger.debug(">> will try to delete this one >> " + thisGuyStr); + + try { + Boolean requireResourceVersion = false; + if (thisGuyId.equals(vidToResCheck)) { + // This is the one vertex that we want to check the resourceId before + // deleting + requireResourceVersion = true; + } + this.serializer.delete(thisVtx, resVersion, requireResourceVersion); + } catch (AAIException ae) { + String errorCode = ae.getErrorObject().getErrorCode(); + if (errorCode.equals("6130") || errorCode.equals("6131")) { + // They didn't pass the correct resource-version for the top node. + throw ae; + } else { + ErrorLogHelper.logException(ae); + String errText = ae.getErrorObject().getErrorText(); + String errDetail = ae.getMessage(); + logger.debug("Exception when deleting " + thisGuyStr + ". ErrorCode = " + + errorCode + ", errorText = " + errText + ", details = " + errDetail); + } + } catch (Exception e) { + // We'd expect to get a "node not found" here sometimes depending on the order + // that + // the model has us finding / deleting nodes. + // Ignore the exception - but log it so we can see what happened. + AAIException aaiException = + new AAIException("AAI_6154", thisGuyStr + ". msg = " + e.getMessage()); + ErrorLogHelper.logException(aaiException); + + } + + // We can't depend on a thrown exception to tell us if a node was deleted since it + // may + // have been auto=deleted before this removeAaiNode() call. + // --- Not sure if we would want to check anything here -- because the + // graph.commit() is done outside of this call. + + deleteIt = true; + } else { + // --- DEBUG ---- + System.out.println(">>>>>>> NOT DELETING THIS ONE >>>> " + thisGuyStr); + List<String> retArr = dbMethHelper.getVertexProperties(thisVtx); + for (String info : retArr) { + System.out.println(info); + } + // --- DEBUG ---- + } + } + + // Now call this routine for the sub-resultSets + List<ResultSet> subResultSetList = resSet.getSubResultSet(); + Iterator<ResultSet> subResSetIter = subResultSetList.iterator(); + while (subResSetIter.hasNext()) { + ResultSet tmpSubResSet = subResSetIter.next(); + retHash = deleteAsNeededFromResultSet(transId, fromAppId, tmpSubResSet, vidToResCheck, + apiVer, resVersion, retHash); + } + + if (deleteIt) { + retHash.put(thisGuyId, thisGuyStr); + } + + return retHash; + + }// deleteAsNeededFromResultSet() + + /** + * Query by named query (old version). + * + * @param transId the trans id + * @param fromAppId the from app id + * @param namedQueryUuid the named query uuid + * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate + * the first nodes of instance data + * @param apiVer the api ver + * @return resultSet + * @throws AAIException the AAI exception + */ + public List<ResultSet> queryByNamedQuery(String transId, String fromAppId, + String namedQueryUuid, List<Map<String, Object>> startNodeFilterArrayOfHashes, + String apiVer) throws AAIException { + + String dummyCutPoint = null; + Map<String, Object> dummySecondaryFilterHash = null; + + return queryByNamedQuery(transId, fromAppId, namedQueryUuid, startNodeFilterArrayOfHashes, + apiVer, dummyCutPoint, dummySecondaryFilterHash); + } + + /** + * Query by named query. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param namedQueryUuid the named query uuid + * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate + * the first nodes of instance data + * @param apiVer the api ver + * @param secondaryFilterCutPoint nodeType where we will prune if secondary filter is not met + * @param secondaryFilterHash secondary filter params + * @return resultSet + * @throws AAIException the AAI exception + */ + public List<ResultSet> queryByNamedQuery(String transId, String fromAppId, + String namedQueryUuid, List<Map<String, Object>> startNodeFilterArrayOfHashes, + String apiVer, String secondaryFilterCutPoint, Map<String, Object> secondaryFilterHash) + throws AAIException { + + final String transId_f = transId; + final String fromAppId_f = fromAppId; + final String namedQueryUuid_f = namedQueryUuid; + final List<Map<String, Object>> startNodeFilterArrayOfHashes_f = + startNodeFilterArrayOfHashes; + final String apiVer_f = apiVer; + final String secondaryFilterCutPoint_f = secondaryFilterCutPoint; + final Map<String, Object> secondaryFilterHash_f = secondaryFilterHash; + + // Find out what our time-limit should be + int timeLimitSec = 0; + String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec"); + if (timeLimitString != null && !timeLimitString.equals("")) { + try { + timeLimitSec = Integer.parseInt(timeLimitString); + } catch (Exception nfe) { + // Don't worry, we will leave the limit as zero - which tells us not to use it. + } + } + + if (timeLimitSec <= 0) { + // We will NOT be using a timer + return queryByNamedQuery_Timed(transId, fromAppId, namedQueryUuid, + startNodeFilterArrayOfHashes, apiVer, secondaryFilterCutPoint_f, + secondaryFilterHash_f); + } + + List<ResultSet> resultList = new ArrayList<>(); + TimeLimiter limiter = new SimpleTimeLimiter(); + try { + resultList = limiter.callWithTimeout(new AaiCallable<List<ResultSet>>() { + public List<ResultSet> process() throws AAIException { + return queryByNamedQuery_Timed(transId_f, fromAppId_f, namedQueryUuid_f, + startNodeFilterArrayOfHashes_f, apiVer_f, secondaryFilterCutPoint_f, + secondaryFilterHash_f); + } + }, timeLimitSec, TimeUnit.SECONDS, true); + + } catch (AAIException ae) { + // Re-throw AAIException so we get can tell what happened internally + throw ae; + } catch (UncheckedTimeoutException ute) { + throw new AAIException("AAI_6140", + "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)"); + } catch (Exception e) { + throw new AAIException("AAI_6128", + "Unexpected exception in queryByNamedQuery(): " + e.getMessage()); + } + + return resultList; + } + + /** + * Query by named query timed. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param namedQueryUuid the named query uuid + * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate + * the first nodes of instance data + * @param apiVer the api ver + * @param secondaryFilterCutPoint the nodeType where we will parse for the secondary Filter + * @param secondaryFilterHash the secondary filter hash + * @return resultSet + * @throws AAIException the AAI exception + */ + public List<ResultSet> queryByNamedQuery_Timed(String transId, String fromAppId, + String namedQueryUuid, List<Map<String, Object>> startNodeFilterArrayOfHashes, + String apiVer, String secondaryFilterCutPoint, Map<String, Object> secondaryFilterHash) + throws AAIException { + + // Locate the Query to be used + Vertex queryVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query", + "named-query-uuid", namedQueryUuid); + + // Get the first/top named-query-element used by this query + Iterator<Vertex> vertI = + this.traverseIncidentEdges(EdgeType.TREE, queryVtx, "named-query-element"); + Vertex firstNqElementVert = null; + int count = 0; + String topNType = ""; + while (vertI != null && vertI.hasNext()) { + firstNqElementVert = vertI.next(); + count++; + topNType = getNqElementWidgetType(transId, fromAppId, firstNqElementVert, ""); + } + + if (count < 1) { + // A named query must start with a single top element + throw new AAIException("AAI_6133", + "No top-node defined for named-query-uuid = [" + namedQueryUuid + "]"); + } else if (count > 1) { + // A named query should start with a single top element + throw new AAIException("AAI_6133", + "More than one top-node defined for named-query-uuid = [" + namedQueryUuid + "]"); + } + if ((topNType == null) || topNType.equals("")) { + String msg = "Could not determine the top-node nodeType for Named Query: [" + + namedQueryUuid + "]"; + throw new AAIException("AAI_6133", msg); + } + + // Read the topology into a hash for processing + Multimap<String, String> validNextStepMap = + genTopoMap4NamedQ(transId, fromAppId, queryVtx, namedQueryUuid); + + List<Vertex> startVertList = new ArrayList<>(); + if (startNodeFilterArrayOfHashes.size() == 1) { + // If there is only one set of startFilter info given, then allow it to possibly not be + // defining just one start node. + Map<String, Object> tmpHash = startNodeFilterArrayOfHashes.get(0); + Set<String> propKeySet = tmpHash.keySet(); + Iterator<String> propIter = propKeySet.iterator(); + Introspector obj = loader.introspectorFromName(topNType); + Set<String> keys = obj.getKeys(); + boolean foundIndexedField = false; + int propertiesSet = 0; + while (propIter.hasNext()) { + String oldVtxKey = propIter.next(); + String newKey = oldVtxKey; + String[] parts = oldVtxKey.split("\\."); + if (parts.length == 2) { + newKey = parts[1]; + } + Object obVal = tmpHash.get(oldVtxKey); + if (obj.hasProperty(newKey)) { + if (keys.contains(newKey)) { + foundIndexedField = true; + } + obj.setValue(newKey, obVal); + propertiesSet++; + } + } + // we found all the properties in the startNodeType + if (propertiesSet == propKeySet.size()) { + if (foundIndexedField) { + QueryBuilder builder = this.engine.getQueryBuilder().exactMatchQuery(obj); + startVertList = builder.toList(); + } else { + // force a filter from aai-node-type + QueryBuilder builder = this.engine.getQueryBuilder().createContainerQuery(obj) + .exactMatchQuery(obj); + startVertList = builder.toList(); + } + } else { + Optional<Vertex> tmpVtx = dbMethHelper.searchVertexByIdentityMap(topNType, + startNodeFilterArrayOfHashes.get(0)); + // Only found one, so just use it. + if (tmpVtx.isPresent()) { + startVertList.add(tmpVtx.get()); + } + } + } else { + // Since they give an array of startNodeFilterHash info, we expect each one + // to just point to one node. + for (int i = 0; i < startNodeFilterArrayOfHashes.size(); i++) { + // Locate the starting node for each set of data + Optional<Vertex> tmpVtx = dbMethHelper.searchVertexByIdentityMap(topNType, + startNodeFilterArrayOfHashes.get(i)); + if (tmpVtx.isPresent()) { + startVertList.add(tmpVtx.get()); + } + } + } + + if (startVertList.isEmpty()) { + throw new AAIException("AAI_6114", + "No Node of type " + topNType + " found for properties"); + } + // Make sure they're not bringing back too much data + String maxString = AAIConfig.get("aai.model.query.resultset.maxcount"); + if (maxString != null && !maxString.equals("")) { + int maxSets = Integer.parseInt(maxString); + if (startVertList.size() > maxSets) { + String msg = " Query returns " + startVertList.size() + + " resultSets. Max allowed is: " + maxSets; + throw new AAIException("AAI_6141", msg); + } + } + + // Loop through each start node and get its data + List<ResultSet> resSetList = new ArrayList<>(); + for (int i = 0; i < startVertList.size(); i++) { + Vertex startVtx = startVertList.get(i); + // Collect the data + String elementLocationTrail = topNType; + ArrayList<String> vidsTraversed = new ArrayList<>(); + Map<String, String> emptyDelKeyHash = new HashMap<>(); // Does not apply to Named + // Queries + + // Get the mapping of namedQuery elements to our widget topology for this namedQuery + String incomingTrail = ""; + Map<String, String> currentHash = new HashMap<>(); + + Map<String, String> namedQueryElementHash = collectNQElementHash(transId, fromAppId, + firstNqElementVert, incomingTrail, currentHash, vidsTraversed, 0); + + vidsTraversed = new ArrayList<>(); + ResultSet tmpResSet = collectInstanceData(transId, fromAppId, startVtx, + elementLocationTrail, validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, + namedQueryElementHash, apiVer); + resSetList.add(tmpResSet); + } + + // If a secondary filter was defined, we will prune the collected instance data result + // set(s) based on it. + List<ResultSet> prunedResSetList = new ArrayList<>(); + if (resSetList != null && !resSetList.isEmpty()) { + for (int i = 0; i < resSetList.size(); i++) { + if (secondaryFilterCutPoint == null || secondaryFilterCutPoint.equals("") + || secondaryFilterHash == null) { + // They didn't want to do any pruning, so just use the results we already had + prunedResSetList.add(resSetList.get(i)); + } else { + ResultSet tmpResSet = pruneResultSet(resSetList.get(i), secondaryFilterCutPoint, + secondaryFilterHash); + if (tmpResSet != null) { + prunedResSetList.add(tmpResSet); + } + } + } + } + + // Since a NamedQuery can mark some nodes as "do-not-display", we need to collapse our + // resultSet so + // does not display those nodes. + List<ResultSet> collapsedResSetList = new ArrayList<>(); + if (prunedResSetList != null && !prunedResSetList.isEmpty()) { + for (int i = 0; i < prunedResSetList.size(); i++) { + // Note - a single resultSet could be collapsed into many smaller ones if they + // marked all the "top" node-elements as do-not-output. Ie. the query may + // have had a top-node of "generic-vnf" which joins down to different l-interfaces. + // If they only want to see the l-interfaces, then a single result set + // would be "collapsed" into many separate resultSets - each of which is + // just a single l-interface. + List<ResultSet> tmpResSetList = collapseForDoNotOutput(prunedResSetList.get(i)); + if (tmpResSetList != null && !tmpResSetList.isEmpty()) { + for (int x = 0; x < tmpResSetList.size(); x++) { + // showResultSet( tmpResSetList.get(x), 0 ); //DEBUG-- this was just for + // testing + collapsedResSetList.add(tmpResSetList.get(x)); + } + } + } + } + + return collapsedResSetList; + + }// End of queryByNamedQuery() + + /** + * Prune a result set as per a secondary filter. + * + * @param resSetVal the res set val + * @param cutPointType the nodeType where the trim will happen + * @param secFilterHash hash of properties and values to use as the secondary filter + * @return pruned result set + * @throws AAIException the AAI exception + */ + public ResultSet pruneResultSet(ResultSet resSetVal, String cutPointType, + Map<String, Object> secFilterHash) throws AAIException { + + // Given a ResultSet and some secondary filter info, do pruning as needed + ResultSet pResSet = new ResultSet(); + + // For this ResultSet, we will see if we are on a node of the type that is our cutPoint; + // then only keep it if we peek "below" and see a match for our filter. + + String nt = resSetVal.getVert().<String>property(AAIProperties.NODE_TYPE).orElse(null); + if (nt != null && nt.equals(cutPointType)) { + // We are on the type of node that may need to be "pruned" along with it's sub-results + if (!satisfiesFilters(resSetVal, secFilterHash)) { + // Return an empty result set since we are pruning at this level. + return pResSet; + } + } + + // If we made it to here, we will not be pruning at this level, so we will + // be returning a copy of this resultSet that has it's subResults pruned (as needed). + pResSet.setVert(resSetVal.getVert()); + pResSet.setDoNotOutputFlag(resSetVal.getDoNotOutputFlag()); + pResSet.setExtraPropertyHash(resSetVal.getExtraPropertyHash()); + pResSet.setLocationInModelSubGraph(resSetVal.getLocationInModelSubGraph()); + pResSet.setNewDataDelFlag(resSetVal.getNewDataDelFlag()); + pResSet.setPropertyLimitDesc(resSetVal.getPropertyLimitDesc()); + pResSet.setPropertyOverRideHash(resSetVal.getPropertyOverRideHash()); + + if (!resSetVal.getSubResultSet().isEmpty()) { + ListIterator<ResultSet> listItr = resSetVal.getSubResultSet().listIterator(); + List<ResultSet> newSubSetList = new ArrayList<>(); + while (listItr.hasNext()) { + ResultSet tmpSubResSet = + pruneResultSet(listItr.next(), cutPointType, secFilterHash); + if (tmpSubResSet.getVert() != null) { + // This one wasn't pruned - so keep it. + newSubSetList.add(tmpSubResSet); + } + } + pResSet.setSubResultSet(newSubSetList); + } + + return pResSet; + + }// End pruneResultSet() + + /** + * Satisfies hash of filters. + * + * @param resSet the res set + * @param filterHash the filter hash + * @return true, if successful + * @throws AAIException the AAI exception + */ + public boolean satisfiesFilters(ResultSet resSet, Map<String, Object> filterHash) + throws AAIException { + + if (filterHash.isEmpty()) { + // Nothing to look for, so no, we didn't find it. + return false; + } + + Iterator<?> it = filterHash.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry<?, ?> filtEntry = (Map.Entry<?, ?>) it.next(); + String propNodeTypeDotName = (filtEntry.getKey()).toString(); + String fpv = (filtEntry.getValue()).toString(); + + int periodLoc = propNodeTypeDotName.indexOf('.'); + if (periodLoc <= 0) { + String emsg = "Bad filter param key passed in: [" + propNodeTypeDotName + + "]. Expected format = [nodeName.paramName]\n"; + throw new AAIException("AAI_6120", emsg); + } else { + String fnt = propNodeTypeDotName.substring(0, periodLoc); + String fpn = propNodeTypeDotName.substring(periodLoc + 1); + if (filterMetByThisSet(resSet, fnt, fpn, fpv)) { + // System.out.println(" DEBUG -- satisfied/matched filter: [" + fnt + "|" + fpn + // + "|" + fpv + "]."); + } else { + // System.out.println(" DEBUG -- NOT satisfied/matched filter: [" + fnt + "|" + + // fpn + "|" + fpv + "]."); + return false; + } + } + } + + // Made it through all the filters -- it found what we were looking for. + return true; + + }// end of satisfiesFilters() + + /** + * Filter met by this set. + * + * @param resSet the res set + * @param filtNodeType the filt node type + * @param filtPropName the filt prop name + * @param filtPropVal the filt prop val + * @return true, if successful + */ + public boolean filterMetByThisSet(ResultSet resSet, String filtNodeType, String filtPropName, + String filtPropVal) { // Note - we are just looking for a positive match for one filter for this resultSet - // NOTE: we're expecting the filter to have a format like this: "nodeType.parameterName:parameterValue" - - Vertex vert = resSet.getVert(); - if( vert == null ){ - return false; - } - else { - String nt = resSet.getVert().<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( nt.equals( filtNodeType ) ){ - if( filtPropName.equals("vertex-id") ){ - // vertex-id can't be gotten the same way as other properties - String thisVtxId = vert.id().toString(); - if( thisVtxId.equals(filtPropVal) ){ - return true; - } - } - else { - Object thisValObj = vert.property(filtPropName).orElse(null); - if( thisValObj != null ){ - String thisVal = thisValObj.toString(); - if( thisVal.equals(filtPropVal) ){ - return true; - } - } - } - } - } - - // Didn't find a match at the this level, so check the sets below it meet the criteria - if( resSet.getSubResultSet() != null ){ - ListIterator<ResultSet> listItr = resSet.getSubResultSet().listIterator(); - while( listItr.hasNext() ){ - if( filterMetByThisSet(listItr.next(), filtNodeType, filtPropName, filtPropVal) ){ - return true; - } - } - } - - return false; - - }// end of filterMetByThisSet() - - - - /** - * Collapse for do not output. - * - * @param resSetVal the res set val - * @return the array list - * @throws AAIException the AAI exception - */ - public List<ResultSet> collapseForDoNotOutput(ResultSet resSetVal ) - throws AAIException { - - // Given a ResultSet -- if it is tagged to NOT be output, then replace it with - // it's sub-ResultSets if it has any. - List<ResultSet> colResultSet = new ArrayList<>(); - - if( resSetVal.getDoNotOutputFlag().equals("true") ){ - // This ResultSet isn't to be displayed, so replace it with it's sub-ResultSets - List<ResultSet> subResList = resSetVal.getSubResultSet(); - for( int k = 0; k < subResList.size(); k++ ){ - List<ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(k)); - colResultSet.addAll(newSubResList); - } - } - else { - // This set will be displayed - colResultSet.add(resSetVal); - } - - // For each result set now at this level, call this same routine to collapse their sub-resultSets - for( int i = 0; i < colResultSet.size(); i++ ){ - List<ResultSet> newSubSet = new ArrayList<>(); - List<ResultSet> subResList = colResultSet.get(i).getSubResultSet(); - for( int n = 0; n < subResList.size(); n++ ){ - List<ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(n)); - newSubSet.addAll(newSubResList); - } - // Replace the old subResultSet with the collapsed set - colResultSet.get(i).setSubResultSet(newSubSet); - } - - return colResultSet; - - }// End collapseForDoNotOutput() - - - - /** - * Collect instance data. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param thisLevelElemVtx the element vtx at this level - * @param thisVertsTrail the this verts trail - * @param validNextStepMap the valid next step map -- hash of valid next steps (node types) for this model - * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point - * @param levelCounter the level counter - * @param delKeyHash -- hashMap of which spots on our topology should be deleted during a modelDelete - * @param namedQueryElementHash - hashMap which maps each spot in our widget topology to the NamedQueryElemment that it maps to - * @param apiVer the api ver - * @return resultSet - * @throws AAIException the AAI exception - */ - public ResultSet collectInstanceData(String transId, String fromAppId, - Vertex thisLevelElemVtx, - String thisVertsTrail, - Multimap<String,String> validNextStepMap, - List<String> vidsTraversed, - int levelCounter, - Map<String,String> delKeyHash, // only applies when collecting data using the default model for delete - Map<String,String> namedQueryElementHash, // only applies to named-query data collecting - String apiVer - ) throws AAIException { - - levelCounter++; - - String thisElemVid = thisLevelElemVtx.id().toString(); - - if( levelCounter > MAX_LEVELS ) { - throw new AAIException("AAI_6125", "collectInstanceData() has looped across more levels than allowed: " + MAX_LEVELS + ". "); - } - - ResultSet rs = new ResultSet(); - if( namedQueryElementHash.containsKey(thisVertsTrail) ){ - // We're collecting data for a named-query, so need to see if we need to do anything special - String nqElUuid = namedQueryElementHash.get(thisVertsTrail); - Vertex nqElementVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query-element", - "named-query-element-uuid", nqElUuid); - - String tmpDoNotShow = nqElementVtx.<String>property("do-not-output").orElse(null); - if( tmpDoNotShow != null && tmpDoNotShow.equals("true") ){ - rs.setDoNotOutputFlag("true"); - } - - if( namedQueryConstraintSaysStop(transId, fromAppId, nqElementVtx, thisLevelElemVtx, apiVer) ){ - // There was a property constraint which says they do not want to collect this vertex or whatever - // might be below it. Just return the empty rs here. - return rs; - } - - String propLimDesc = nqElementVtx.<String>property("property-limit-desc").orElse(null); - if( (propLimDesc != null) && !propLimDesc.equals("") ){ - if (propLimDesc.equalsIgnoreCase("show-all")) { - rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_ALL); - } else if (propLimDesc.equalsIgnoreCase("show-none")) { - rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_NONE); - }else if (propLimDesc.equalsIgnoreCase("name-and-keys-only")) { - rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_NAME_AND_KEYS_ONLY); - } - } - - // Look to see if we need to use an Override of the normal properties - Map<String,Object> tmpPropertyOverRideHash = getNamedQueryPropOverRide(transId, fromAppId, nqElementVtx, thisLevelElemVtx, apiVer); - //System.out.println(" DEBUG --- USING this propertyOverride data set on ResSet [" + tmpPropertyOverRideHash.toString() + "]"); - rs.setPropertyOverRideHash(tmpPropertyOverRideHash); - - // See if we need to look up any "unconnected" data that needs to be associated with this result set - Map<String,Object> tmpExtraPropHash = getNamedQueryExtraDataLookup(transId, fromAppId, nqElementVtx, thisLevelElemVtx, apiVer); - //System.out.println(" DEBUG --- ADDING this EXTRA Lookup data to the ResSet [" + tmpExtraPropHash.toString() + "]"); - rs.setExtraPropertyHash(tmpExtraPropHash); - } - - rs.setVert(thisLevelElemVtx); - rs.setLocationInModelSubGraph(thisVertsTrail); - if( delKeyHash.containsKey(thisVertsTrail) && delKeyHash.get(thisVertsTrail).equals("T") ){ - rs.setNewDataDelFlag("T"); - } - else { - rs.setNewDataDelFlag("F"); - } - - // Use Gremlin-pipeline to just look for edges that go to a valid "next-steps" - Collection <String> validNextStepColl = validNextStepMap.get(thisVertsTrail); - - // Because of how we process linkage-points, we may have duplicate node-types in our next-stepMap (for one step) - // So, to keep from looking (and bringing back) the same data twice, we need to make sure our next-steps are unique - Set<String> validNextStepHashSet = new HashSet<>(); - Iterator <String> ntcItr = validNextStepColl.iterator(); - while( ntcItr.hasNext() ){ - String targetStepStr = ntcItr.next(); - validNextStepHashSet.add(targetStepStr); - } - - List<String> tmpVidsTraversedList = new ArrayList<>(); - tmpVidsTraversedList.addAll(vidsTraversed); - tmpVidsTraversedList.add(thisElemVid); - - Iterator <String> ntItr = validNextStepHashSet.iterator(); - while( ntItr.hasNext() ){ - String targetStep = ntItr.next(); - // NOTE: NextSteps can either be just a nodeType, or can be a nodeType plus - // model-invariant-id-local and model-version-id-local (the two persona properties) - // if those need to be checked also. - // When the persona stuff is part of the step, it is a comma separated string. - // Ie. "nodeType,model-inv-id-local,model-version-id-local" (the two "persona" props) - // - String targetNodeType = ""; - String pmid = ""; - String pmv = ""; - Boolean stepIsJustNT = true; - if( targetStep.contains(",") ){ - stepIsJustNT = false; - String[] pieces = targetStep.split(","); - if( pieces.length != 3 ){ - throw new AAIException("AAI_6128", "Unexpected format for nextStep in model processing = [" - + targetStep + "]. "); - } - else { - targetNodeType = pieces[0]; - pmid = pieces[1]; - pmv = pieces[2]; - } - } - else { - // It's just the nodeType with no other info - targetNodeType = targetStep; - } - - GraphTraversal<Vertex, Vertex> modPipe = null; - if( stepIsJustNT ){ - modPipe = this.engine.asAdmin().getReadOnlyTraversalSource().V(thisLevelElemVtx).both().has(AAIProperties.NODE_TYPE, targetNodeType); - } - else { - modPipe = this.engine.asAdmin().getReadOnlyTraversalSource().V(thisLevelElemVtx).both().has(AAIProperties.NODE_TYPE, targetNodeType).has(addDBAliasedSuffix("model-invariant-id"),pmid).has(addDBAliasedSuffix("model-version-id"),pmv); - } - - if( modPipe == null || !modPipe.hasNext() ){ - //System.out.println("DEBUG - didn't find any [" + targetStep + "] connected to this guy (which is ok)"); - } - else { - while( modPipe.hasNext() ){ - Vertex tmpVert = modPipe.next(); - String tmpVid = tmpVert.id().toString(); - String tmpTrail = thisVertsTrail + "|" + targetStep; - if( !vidsTraversed.contains(tmpVid) ){ - // This is one we would like to use - so we'll include the result set we get for it - ResultSet tmpResSet = collectInstanceData( transId, fromAppId, - tmpVert, tmpTrail, - validNextStepMap, tmpVidsTraversedList, - levelCounter, delKeyHash, namedQueryElementHash, apiVer ); - - rs.getSubResultSet().add(tmpResSet); - } - } - } - } - - return rs; - - } // End of collectInstanceData() - - - /** - * Gen topo map 4 model. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modelVerVertex the model-ver vertex - * @param modelVerId the model-version-id - * @return MultiMap of valid next steps for each potential model-element - * @throws AAIException the AAI exception - */ - public Multimap<String, String> genTopoMap4ModelVer(String transId, String fromAppId, - Vertex modelVerVertex, String modelVerId) - throws AAIException { - - if( modelVerVertex == null ){ - throw new AAIException("AAI_6114", "null modelVerVertex passed to genTopoMap4ModelVer()"); - } - - Multimap<String, String> initialEmptyMap = ArrayListMultimap.create(); - List<String> vidsTraversed = new ArrayList<>(); - String modelType = getModelTypeFromModelVer( modelVerVertex, "" ); - if( modelType.equals("widget") ){ - // A widget model by itself does not have a topoplogy. That is - it has no "model-elements" which - // define how it is connected to other things. All it has is a name which ties it to - // an aai-node-type - Iterator<Vertex> vertI= this.traverseIncidentEdges(EdgeType.TREE, modelVerVertex, "model-element"); - if( vertI != null && vertI.hasNext() ){ - throw new AAIException("AAI_6132", "Bad Model Definition: Widget Model has a startsWith edge to a model-element. " - + " model-version-id = " + modelVerId); - } - else { - return initialEmptyMap; - } - } - - String firstModelVerId = modelVerVertex.<String>property("model-version-id").orElse(null); - String firstModelVersion = modelVerVertex.<String>property("model-version").orElse(null); - if( firstModelVerId == null || firstModelVerId.equals("") || firstModelVersion == null || firstModelVersion.equals("") ){ - throw new AAIException("AAI_6132", "Bad Model Definition: Bad model-version-id or model-version. model-version-id = " - + modelVerId); - } - - Vertex firstElementVertex = getTopElementForSvcOrResModelVer( modelVerVertex, "" ); - Vertex firstEleModVerVtx = getModelVerThatElementRepresents( firstElementVertex, "" ); - String firstElemModelType = getModelTypeFromModelVer( firstEleModVerVtx, "" ); - if( ! firstElemModelType.equals("widget") ){ - throw new AAIException("AAI_6132", "Bad Model Definition: First element must correspond to a widget type model. Model UUID = " - + modelVerId); - } - - Vertex firstModVtx = getModelGivenModelVer( modelVerVertex, "" ); - String firstModelInvId = firstModVtx.<String>property("model-invariant-id").orElse(null); - if( firstModelInvId == null || firstModelInvId.equals("") ){ - throw new AAIException("AAI_6132", "Bad Model Definition: Could not find model.model-invariant-id given model-ver.model-version-id = " - + modelVerId); - } - - return collectTopology4ModelVer( transId, fromAppId, - firstElementVertex, "", initialEmptyMap, vidsTraversed, 0, null, firstModelInvId, firstModelVersion ); - } // End of genTopoMap4ModelVer() - - - public List<String> makeSureItsAnArrayList( String listStringVal ){ - // We're sometimes getting a String back on db properties that should be ArrayList<String> - // Seems to be how they're defined in OXM - whether they use a "xml-wrapper" or not - // Need to translate them into ArrayLists sometimes... - - List<String> retArrList = new ArrayList<>(); - String listString = listStringVal; - listString = listString.replace(" ", ""); - listString = listString.replace("\"", ""); - listString = listString.replace("[", ""); - listString = listString.replace("]", ""); - String [] pieces = listString.split(","); - if(pieces.length > 0){ - retArrList.addAll(Arrays.asList(pieces)); - } - return retArrList; - } - - - /** - * Gets the mod constraint hash. - * - * @param modelElementVtx the model element vtx - * @param currentHash -- the current ModelConstraint's that this routine will add to if it finds any. - * @return HashMap of model-constraints that will be looked at for this model-element and what's "below" it. - * @throws AAIException the AAI exception - */ - public Map<String, Vertex> getModConstraintHash(Vertex modelElementVtx, Map<String, Vertex> currentHash ) - throws AAIException { - - // For a given model-element vertex, look to see if there are any "model-constraint" elements that is has - // an OUT "uses" edge to. If it does, then get any "constrained-element-set" nodes that are pointed to - // by the "model-constraint". That will be the replacement "constrained-element-set". The UUID of the - // "constrained-element-set" that it is supposed to replace is found in the property: - // model-constraint.constrained-element-set-uuid-to-replace - // - // For now, that is the only type of model-constraint allowed, so that is all we will look for. - // Pass back any of these "constrained-element-set" nodes along with any that were passed in by - // the "currentHash" parameter. - - if( modelElementVtx == null ){ - String msg = " null modelElementVtx passed to getModConstraintHash() "; - throw new AAIException("AAI_6114", msg); - } - - String modelType = modelElementVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( modelType == null || (!modelType.equals("model-element")) ){ - String msg = " getModConstraintHash() called with wrong type model: [" + modelType + "]. "; - throw new AAIException("AAI_6114", msg); - } - - Map<String, Vertex> thisHash = new HashMap<>(); - if( currentHash != null ){ - thisHash.putAll(currentHash); - } - - int count = 0; - List<Vertex> modelConstraintArray = new ArrayList<>(); - Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, modelElementVtx, "model-constraint"); - while( vertI != null && vertI.hasNext() ){ - Vertex tmpVert = vertI.next(); - String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( (connectToType != null) && connectToType.equals("model-constraint") ){ - // We need to find the constrained element set pointed to by this and add it to the Hash to return - modelConstraintArray.add(tmpVert); - count++; - } - } - - if( count > 0 ) { - for( int i = 0; i < count; i++ ){ - Vertex vtxOfModelConstraint = modelConstraintArray.get(i); - String uuidOfTheOneToBeReplaced = vtxOfModelConstraint.<String>property("constrained-element-set-uuid-2-replace").orElse(null); - // We have the UUID of the constrained-element-set that will be superseded, now find the - // constrained-element-set to use in its place - Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.TREE, vtxOfModelConstraint, "constrained-element-set"); - while( mvertI != null && mvertI.hasNext() ){ - // There better only be one... - Vertex tmpVert = mvertI.next(); - String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( (connectToType != null) && connectToType.equals("constrained-element-set") ){ - // This is the "constrained-element-set" that we want to use as the Replacement - thisHash.put(uuidOfTheOneToBeReplaced, tmpVert ); - } - } - } - return thisHash; - } - else { - // Didn't find anything to add, so just return what they passed in. - return currentHash; - } - - } // End of getModConstraintHash() - - - /** - * Gets the top element vertex for service or resource model. - * - * @param modelVerVtx the model-ver vertex - * @return first element pointed to by this model-ver - * @throws AAIException the AAI exception - */ - public Vertex getTopElementForSvcOrResModelVer(Vertex modelVerVtx, String trail ) - throws AAIException { - - // For a "resource" or "service" type model, return the "top" element in that model - if( modelVerVtx == null ){ - String msg = " null modelVertex passed to getTopoElementForSvcOrResModelVer() at [" + trail + "]. "; - throw new AAIException("AAI_6114", msg); - } - - String modelVerId = modelVerVtx.<String>property("model-version-id").orElse(null); - if( modelVerId == null ){ - String nt = modelVerVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( nt != null && !nt.equals("model-ver") ){ - String msg = "Illegal model defined: model element pointing to nodeType: [" - + nt + "], should be pointing to: [model-ver] at [" + trail + "]. "; - throw new AAIException("AAI_6132", msg); - } - } - - Vertex firstElementVertex = null; - - Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, modelVerVtx, "model-element"); - int elCount = 0; - while( vertI != null && vertI.hasNext() ){ - elCount++; - firstElementVertex = vertI.next(); - } - - if( elCount > 1 ){ - String msg = "Illegal model defined: More than one first element defined for model-ver-id = " + - modelVerId + " at [" + trail + "]. "; - throw new AAIException("AAI_6132", msg); - } - - if( firstElementVertex == null ){ - String msg = "Could not find first model element for model-ver-id = " - + modelVerId + " at [" + trail + "]. "; - throw new AAIException("AAI_6132", msg); - } - - return firstElementVertex; - - } // End of getTopElementForSvcOrResModelVer() - - - - /** - * Gets the named query prop over ride. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param namedQueryElementVertex the named query element vertex - * @param instanceVertex the instance vertex - * @param apiVer the api ver - * @return HashMap of alternate properties to return for this element - * @throws AAIException the AAI exception - */ - public Map<String,Object> getNamedQueryPropOverRide(String transId, String fromAppId, - Vertex namedQueryElementVertex, Vertex instanceVertex, String apiVer ) - throws AAIException { - - // If this model-element says that they want an alternative set of properties returned, then pull that - // data out of the instance vertex. - - Map<String,Object> altPropHash = new HashMap<>(); - - if( namedQueryElementVertex == null ){ - String msg = " null namedQueryElementVertex passed to getNamedQueryPropOverRide() "; - throw new AAIException("AAI_6114", msg); - } - - List<String> propCollectList = new ArrayList<>(); - Iterator <VertexProperty<Object>> vpI = namedQueryElementVertex.properties("property-collect-list"); - while( vpI.hasNext() ){ - propCollectList.add((String)vpI.next().value()); - } - - for( int i = 0; i < propCollectList.size(); i++ ){ - String thisPropName = propCollectList.get(i); - Object instanceVal = instanceVertex.<Object>property(thisPropName).orElse(null); - altPropHash.put(thisPropName, instanceVal); - } - - return altPropHash; - - } // End of getNamedQueryPropOverRide() - - - /** - * Named query constraint says stop. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param namedQueryElementVertex the named query element vertex - * @param instanceVertex the instance vertex - * @param apiVer the api ver - * @return true - if a constraint was defined that has not been met by the passed instanceVertex - * @throws AAIException the AAI exception - */ - public Boolean namedQueryConstraintSaysStop(String transId, String fromAppId, - Vertex namedQueryElementVertex, Vertex instanceVertex, String apiVer ) - throws AAIException { - - // For each (if any) property-constraint defined for this named-query-element, we will evaluate if - // the constraint is met or not-met. if there are constraints and any are not-met, then - // we return "true". - - if( namedQueryElementVertex == null ){ - String msg = " null namedQueryElementVertex passed to namedQueryConstraintSaysStop() "; - throw new AAIException("AAI_6114", msg); - } - if( instanceVertex == null ){ - String msg = " null instanceVertex passed to namedQueryConstraintSaysStop() "; - throw new AAIException("AAI_6114", msg); - } - - Iterator<Vertex> constrPipe = this.traverseIncidentEdges(EdgeType.TREE, namedQueryElementVertex, "property-constraint"); - if( constrPipe == null || !constrPipe.hasNext() ){ - // There's no "property-constraint" defined for this named-query-element. No problem. - return false; - } - - while( constrPipe.hasNext() ){ - Vertex constrVtx = constrPipe.next(); - // We found a property constraint that we will need to check - String conType = constrVtx.<String>property("constraint-type").orElse(null); - if( (conType == null) || conType.equals("")){ - String msg = " Bad property-constraint (constraint-type) found in Named Query definition. "; - throw new AAIException("AAI_6133", msg); - } - String propName = constrVtx.<String>property("property-name").orElse(null); - if( (propName == null) || propName.equals("")){ - String msg = " Bad property-constraint (property-name) found in Named Query definition. "; - throw new AAIException("AAI_6133", msg); - } - String propVal = constrVtx.<String>property("property-value").orElse(null); - if( (propVal == null) || propVal.equals("")){ - String msg = " Bad property-constraint (propVal) found in Named Query definition. "; - throw new AAIException("AAI_6133", msg); - } - - // See if that constraint is met or not - String val = instanceVertex.<String>property(propName).orElse(null); - if( val == null ){ - val = ""; - } - - if( conType.equals("EQUALS") ){ - if( !val.equals(propVal) ){ - // This constraint was not met - return true; - } - } - else if( conType.equals("NOT-EQUALS") ){ - if( val.equals(propVal) ){ - // This constraint was not met - return true; - } - } - else { - String msg = " Bad property-constraint (constraint-type) found in Named Query definition. "; - throw new AAIException("AAI_6133", msg); - } - } - - return false; - - } // End of namedQueryConstraintSaysStop() - - - /** - * Gets the named query extra data lookup. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param namedQueryElementVertex the named query element vertex - * @param instanceVertex the instance vertex - * @param apiVer the api ver - * @return HashMap of alternate properties to return for this element - * @throws AAIException the AAI exception - */ - public Map<String,Object> getNamedQueryExtraDataLookup(String transId, String fromAppId, - Vertex namedQueryElementVertex, Vertex instanceVertex, String apiVer ) - throws AAIException { - - // For each (if any) related-lookup defined for this named-query-element, we will go and - // and try to find it. All the related-lookup data will get put in a hash and returned. - - if( namedQueryElementVertex == null ){ - String msg = " null namedQueryElementVertex passed to getNamedQueryExtraDataLookup() "; - throw new AAIException("AAI_6114", msg); - } - if( instanceVertex == null ){ - String msg = " null instanceVertex passed to getNamedQueryExtraDataLookup() "; - throw new AAIException("AAI_6114", msg); - } - - Map<String,Object> retHash = new HashMap<>(); - - Iterator<Vertex> lookPipe = this.traverseIncidentEdges(EdgeType.TREE, namedQueryElementVertex, "related-lookup"); - if( lookPipe == null || !lookPipe.hasNext() ){ - // There's no "related-lookup" defined for this named-query-element. No problem. - return retHash; - } - - while( lookPipe.hasNext() ){ - Vertex relLookupVtx = lookPipe.next(); - // We found a related-lookup record to try and use - String srcProp = relLookupVtx.<String>property("source-node-property").orElse(null); - String srcNodeType = relLookupVtx.<String>property("source-node-type").orElse(null); - srcProp = getPropNameWithAliasIfNeeded(srcNodeType, srcProp); - - if( (srcProp == null) || srcProp.equals("")){ - String msg = " Bad related-lookup (source-node-property) found in Named Query definition. "; - throw new AAIException("AAI_6133", msg); - } - String targetNodeType = relLookupVtx.<String>property("target-node-type").orElse(null); - if( (targetNodeType == null) || targetNodeType.equals("")){ - String msg = " Bad related-lookup (targetNodeType) found in Named Query definition. "; - throw new AAIException("AAI_6133", msg); - } - String targetProp = relLookupVtx.<String>property("target-node-property").orElse(null); - targetProp = getPropNameWithAliasIfNeeded(targetNodeType, targetProp); - - if( (targetProp == null) || targetProp.equals("")){ - String msg = " Bad related-lookup (target-node-property) found in Named Query definition. "; - throw new AAIException("AAI_6133", msg); - } - - List<String> propCollectList = new ArrayList<>(); - Iterator <VertexProperty<Object>> vpI = relLookupVtx.properties("property-collect-list"); - while( vpI.hasNext() ){ - propCollectList.add((String)vpI.next().value()); - } - - // Use the value from the source to see if we can find ONE target record using the - // value from the source - String valFromInstance = instanceVertex.<String>property(srcProp).orElse(null); - if( valFromInstance == null ){ - // if there is no key to use to go look up something, we should end it here and just - // note what happened - no need to try to look something up by an empty key - logger.debug("WARNING - the instance data node of type [" + srcNodeType - + "] did not have a value for property [" + srcProp - + "], so related-lookup is being abandoned."); - return retHash; - } - - Map<String,Object> propHash = new HashMap<>(); - propHash.put(targetProp, valFromInstance); - - Optional<Vertex> result = dbMethHelper.locateUniqueVertex(targetNodeType, propHash); - if (!result.isPresent()) { - // If it can't find the lookup node, don't fail, just log that it couldn't be found --- + // NOTE: we're expecting the filter to have a format like this: + // "nodeType.parameterName:parameterValue" + + Vertex vert = resSet.getVert(); + if (vert == null) { + return false; + } else { + String nt = resSet.getVert().<String>property(AAIProperties.NODE_TYPE).orElse(null); + if (nt.equals(filtNodeType)) { + if (filtPropName.equals("vertex-id")) { + // vertex-id can't be gotten the same way as other properties + String thisVtxId = vert.id().toString(); + if (thisVtxId.equals(filtPropVal)) { + return true; + } + } else { + Object thisValObj = vert.property(filtPropName).orElse(null); + if (thisValObj != null) { + String thisVal = thisValObj.toString(); + if (thisVal.equals(filtPropVal)) { + return true; + } + } + } + } + } + + // Didn't find a match at the this level, so check the sets below it meet the criteria + if (resSet.getSubResultSet() != null) { + ListIterator<ResultSet> listItr = resSet.getSubResultSet().listIterator(); + while (listItr.hasNext()) { + if (filterMetByThisSet(listItr.next(), filtNodeType, filtPropName, filtPropVal)) { + return true; + } + } + } + + return false; + + }// end of filterMetByThisSet() + + /** + * Collapse for do not output. + * + * @param resSetVal the res set val + * @return the array list + * @throws AAIException the AAI exception + */ + public List<ResultSet> collapseForDoNotOutput(ResultSet resSetVal) throws AAIException { + + // Given a ResultSet -- if it is tagged to NOT be output, then replace it with + // it's sub-ResultSets if it has any. + List<ResultSet> colResultSet = new ArrayList<>(); + + if (resSetVal.getDoNotOutputFlag().equals("true")) { + // This ResultSet isn't to be displayed, so replace it with it's sub-ResultSets + List<ResultSet> subResList = resSetVal.getSubResultSet(); + for (int k = 0; k < subResList.size(); k++) { + List<ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(k)); + colResultSet.addAll(newSubResList); + } + } else { + // This set will be displayed + colResultSet.add(resSetVal); + } + + // For each result set now at this level, call this same routine to collapse their + // sub-resultSets + for (int i = 0; i < colResultSet.size(); i++) { + List<ResultSet> newSubSet = new ArrayList<>(); + List<ResultSet> subResList = colResultSet.get(i).getSubResultSet(); + for (int n = 0; n < subResList.size(); n++) { + List<ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(n)); + newSubSet.addAll(newSubResList); + } + // Replace the old subResultSet with the collapsed set + colResultSet.get(i).setSubResultSet(newSubSet); + } + + return colResultSet; + + }// End collapseForDoNotOutput() + + /** + * Collect instance data. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param thisLevelElemVtx the element vtx at this level + * @param thisVertsTrail the this verts trail + * @param validNextStepMap the valid next step map -- hash of valid next steps (node types) for + * this model + * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get + * to this point + * @param levelCounter the level counter + * @param delKeyHash -- hashMap of which spots on our topology should be deleted during a + * modelDelete + * @param namedQueryElementHash - hashMap which maps each spot in our widget topology to the + * NamedQueryElemment that it maps to + * @param apiVer the api ver + * @return resultSet + * @throws AAIException the AAI exception + */ + public ResultSet collectInstanceData(String transId, String fromAppId, Vertex thisLevelElemVtx, + String thisVertsTrail, Multimap<String, String> validNextStepMap, + List<String> vidsTraversed, int levelCounter, Map<String, String> delKeyHash, // only + // applies + // when + // collecting + // data using + // the default + // model for + // delete + Map<String, String> namedQueryElementHash, // only applies to named-query data collecting + String apiVer) throws AAIException { + + levelCounter++; + + String thisElemVid = thisLevelElemVtx.id().toString(); + + if (levelCounter > MAX_LEVELS) { + throw new AAIException("AAI_6125", + "collectInstanceData() has looped across more levels than allowed: " + MAX_LEVELS + + ". "); + } + + ResultSet rs = new ResultSet(); + if (namedQueryElementHash.containsKey(thisVertsTrail)) { + // We're collecting data for a named-query, so need to see if we need to do anything + // special + String nqElUuid = namedQueryElementHash.get(thisVertsTrail); + Vertex nqElementVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query-element", + "named-query-element-uuid", nqElUuid); + + String tmpDoNotShow = nqElementVtx.<String>property("do-not-output").orElse(null); + if (tmpDoNotShow != null && tmpDoNotShow.equals("true")) { + rs.setDoNotOutputFlag("true"); + } + + if (namedQueryConstraintSaysStop(transId, fromAppId, nqElementVtx, thisLevelElemVtx, + apiVer)) { + // There was a property constraint which says they do not want to collect this + // vertex or whatever + // might be below it. Just return the empty rs here. + return rs; + } + + String propLimDesc = nqElementVtx.<String>property("property-limit-desc").orElse(null); + if ((propLimDesc != null) && !propLimDesc.equals("")) { + if (propLimDesc.equalsIgnoreCase("show-all")) { + rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_ALL); + } else if (propLimDesc.equalsIgnoreCase("show-none")) { + rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_NONE); + } else if (propLimDesc.equalsIgnoreCase("name-and-keys-only")) { + rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_NAME_AND_KEYS_ONLY); + } + } + + // Look to see if we need to use an Override of the normal properties + Map<String, Object> tmpPropertyOverRideHash = getNamedQueryPropOverRide(transId, + fromAppId, nqElementVtx, thisLevelElemVtx, apiVer); + // System.out.println(" DEBUG --- USING this propertyOverride data set on ResSet [" + + // tmpPropertyOverRideHash.toString() + "]"); + rs.setPropertyOverRideHash(tmpPropertyOverRideHash); + + // See if we need to look up any "unconnected" data that needs to be associated with + // this result set + Map<String, Object> tmpExtraPropHash = getNamedQueryExtraDataLookup(transId, fromAppId, + nqElementVtx, thisLevelElemVtx, apiVer); + // System.out.println(" DEBUG --- ADDING this EXTRA Lookup data to the ResSet [" + + // tmpExtraPropHash.toString() + "]"); + rs.setExtraPropertyHash(tmpExtraPropHash); + } + + rs.setVert(thisLevelElemVtx); + rs.setLocationInModelSubGraph(thisVertsTrail); + if (delKeyHash.containsKey(thisVertsTrail) && delKeyHash.get(thisVertsTrail).equals("T")) { + rs.setNewDataDelFlag("T"); + } else { + rs.setNewDataDelFlag("F"); + } + + // Use Gremlin-pipeline to just look for edges that go to a valid "next-steps" + Collection<String> validNextStepColl = validNextStepMap.get(thisVertsTrail); + + // Because of how we process linkage-points, we may have duplicate node-types in our + // next-stepMap (for one step) + // So, to keep from looking (and bringing back) the same data twice, we need to make sure + // our next-steps are unique + Set<String> validNextStepHashSet = new HashSet<>(); + Iterator<String> ntcItr = validNextStepColl.iterator(); + while (ntcItr.hasNext()) { + String targetStepStr = ntcItr.next(); + validNextStepHashSet.add(targetStepStr); + } + + List<String> tmpVidsTraversedList = new ArrayList<>(); + tmpVidsTraversedList.addAll(vidsTraversed); + tmpVidsTraversedList.add(thisElemVid); + + Iterator<String> ntItr = validNextStepHashSet.iterator(); + while (ntItr.hasNext()) { + String targetStep = ntItr.next(); + // NOTE: NextSteps can either be just a nodeType, or can be a nodeType plus + // model-invariant-id-local and model-version-id-local (the two persona properties) + // if those need to be checked also. + // When the persona stuff is part of the step, it is a comma separated string. + // Ie. "nodeType,model-inv-id-local,model-version-id-local" (the two "persona" props) + // + String targetNodeType = ""; + String pmid = ""; + String pmv = ""; + Boolean stepIsJustNT = true; + if (targetStep.contains(",")) { + stepIsJustNT = false; + String[] pieces = targetStep.split(","); + if (pieces.length != 3) { + throw new AAIException("AAI_6128", + "Unexpected format for nextStep in model processing = [" + targetStep + + "]. "); + } else { + targetNodeType = pieces[0]; + pmid = pieces[1]; + pmv = pieces[2]; + } + } else { + // It's just the nodeType with no other info + targetNodeType = targetStep; + } + + GraphTraversal<Vertex, Vertex> modPipe = null; + if (stepIsJustNT) { + modPipe = this.engine.asAdmin().getReadOnlyTraversalSource().V(thisLevelElemVtx) + .both().has(AAIProperties.NODE_TYPE, targetNodeType); + } else { + modPipe = this.engine.asAdmin().getReadOnlyTraversalSource().V(thisLevelElemVtx) + .both().has(AAIProperties.NODE_TYPE, targetNodeType) + .has(addDBAliasedSuffix("model-invariant-id"), pmid) + .has(addDBAliasedSuffix("model-version-id"), pmv); + } + + if (modPipe == null || !modPipe.hasNext()) { + // System.out.println("DEBUG - didn't find any [" + targetStep + "] connected to + // this guy (which is ok)"); + } else { + while (modPipe.hasNext()) { + Vertex tmpVert = modPipe.next(); + String tmpVid = tmpVert.id().toString(); + String tmpTrail = thisVertsTrail + "|" + targetStep; + if (!vidsTraversed.contains(tmpVid)) { + // This is one we would like to use - so we'll include the result set we get + // for it + ResultSet tmpResSet = collectInstanceData(transId, fromAppId, tmpVert, + tmpTrail, validNextStepMap, tmpVidsTraversedList, levelCounter, + delKeyHash, namedQueryElementHash, apiVer); + + rs.getSubResultSet().add(tmpResSet); + } + } + } + } + + return rs; + + } // End of collectInstanceData() + + /** + * Gen topo map 4 model. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVerVertex the model-ver vertex + * @param modelVerId the model-version-id + * @return MultiMap of valid next steps for each potential model-element + * @throws AAIException the AAI exception + */ + public Multimap<String, String> genTopoMap4ModelVer(String transId, String fromAppId, + Vertex modelVerVertex, String modelVerId) throws AAIException { + + if (modelVerVertex == null) { + throw new AAIException("AAI_6114", + "null modelVerVertex passed to genTopoMap4ModelVer()"); + } + + Multimap<String, String> initialEmptyMap = ArrayListMultimap.create(); + List<String> vidsTraversed = new ArrayList<>(); + String modelType = getModelTypeFromModelVer(modelVerVertex, ""); + if (modelType.equals("widget")) { + // A widget model by itself does not have a topoplogy. That is - it has no + // "model-elements" which + // define how it is connected to other things. All it has is a name which ties it to + // an aai-node-type + Iterator<Vertex> vertI = + this.traverseIncidentEdges(EdgeType.TREE, modelVerVertex, "model-element"); + if (vertI != null && vertI.hasNext()) { + throw new AAIException("AAI_6132", + "Bad Model Definition: Widget Model has a startsWith edge to a model-element. " + + " model-version-id = " + modelVerId); + } else { + return initialEmptyMap; + } + } + + String firstModelVerId = modelVerVertex.<String>property("model-version-id").orElse(null); + String firstModelVersion = modelVerVertex.<String>property("model-version").orElse(null); + if (firstModelVerId == null || firstModelVerId.equals("") || firstModelVersion == null + || firstModelVersion.equals("")) { + throw new AAIException("AAI_6132", + "Bad Model Definition: Bad model-version-id or model-version. model-version-id = " + + modelVerId); + } + + Vertex firstElementVertex = getTopElementForSvcOrResModelVer(modelVerVertex, ""); + Vertex firstEleModVerVtx = getModelVerThatElementRepresents(firstElementVertex, ""); + String firstElemModelType = getModelTypeFromModelVer(firstEleModVerVtx, ""); + if (!firstElemModelType.equals("widget")) { + throw new AAIException("AAI_6132", + "Bad Model Definition: First element must correspond to a widget type model. Model UUID = " + + modelVerId); + } + + Vertex firstModVtx = getModelGivenModelVer(modelVerVertex, ""); + String firstModelInvId = firstModVtx.<String>property("model-invariant-id").orElse(null); + if (firstModelInvId == null || firstModelInvId.equals("")) { + throw new AAIException("AAI_6132", + "Bad Model Definition: Could not find model.model-invariant-id given model-ver.model-version-id = " + + modelVerId); + } + + return collectTopology4ModelVer(transId, fromAppId, firstElementVertex, "", initialEmptyMap, + vidsTraversed, 0, null, firstModelInvId, firstModelVersion); + } // End of genTopoMap4ModelVer() + + public List<String> makeSureItsAnArrayList(String listStringVal) { + // We're sometimes getting a String back on db properties that should be ArrayList<String> + // Seems to be how they're defined in OXM - whether they use a "xml-wrapper" or not + // Need to translate them into ArrayLists sometimes... + + List<String> retArrList = new ArrayList<>(); + String listString = listStringVal; + listString = listString.replace(" ", ""); + listString = listString.replace("\"", ""); + listString = listString.replace("[", ""); + listString = listString.replace("]", ""); + String[] pieces = listString.split(","); + if (pieces.length > 0) { + retArrList.addAll(Arrays.asList(pieces)); + } + return retArrList; + } + + /** + * Gets the mod constraint hash. + * + * @param modelElementVtx the model element vtx + * @param currentHash -- the current ModelConstraint's that this routine will add to if it finds + * any. + * @return HashMap of model-constraints that will be looked at for this model-element and what's + * "below" it. + * @throws AAIException the AAI exception + */ + public Map<String, Vertex> getModConstraintHash(Vertex modelElementVtx, + Map<String, Vertex> currentHash) throws AAIException { + + // For a given model-element vertex, look to see if there are any "model-constraint" + // elements that is has + // an OUT "uses" edge to. If it does, then get any "constrained-element-set" nodes that are + // pointed to + // by the "model-constraint". That will be the replacement "constrained-element-set". The + // UUID of the + // "constrained-element-set" that it is supposed to replace is found in the property: + // model-constraint.constrained-element-set-uuid-to-replace + // + // For now, that is the only type of model-constraint allowed, so that is all we will look + // for. + // Pass back any of these "constrained-element-set" nodes along with any that were passed in + // by + // the "currentHash" parameter. + + if (modelElementVtx == null) { + String msg = " null modelElementVtx passed to getModConstraintHash() "; + throw new AAIException("AAI_6114", msg); + } + + String modelType = modelElementVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if (modelType == null || (!modelType.equals("model-element"))) { + String msg = + " getModConstraintHash() called with wrong type model: [" + modelType + "]. "; + throw new AAIException("AAI_6114", msg); + } + + Map<String, Vertex> thisHash = new HashMap<>(); + if (currentHash != null) { + thisHash.putAll(currentHash); + } + + int count = 0; + List<Vertex> modelConstraintArray = new ArrayList<>(); + Iterator<Vertex> vertI = + this.traverseIncidentEdges(EdgeType.TREE, modelElementVtx, "model-constraint"); + while (vertI != null && vertI.hasNext()) { + Vertex tmpVert = vertI.next(); + String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if ((connectToType != null) && connectToType.equals("model-constraint")) { + // We need to find the constrained element set pointed to by this and add it to the + // Hash to return + modelConstraintArray.add(tmpVert); + count++; + } + } + + if (count > 0) { + for (int i = 0; i < count; i++) { + Vertex vtxOfModelConstraint = modelConstraintArray.get(i); + String uuidOfTheOneToBeReplaced = vtxOfModelConstraint + .<String>property("constrained-element-set-uuid-2-replace").orElse(null); + // We have the UUID of the constrained-element-set that will be superseded, now find + // the + // constrained-element-set to use in its place + Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.TREE, + vtxOfModelConstraint, "constrained-element-set"); + while (mvertI != null && mvertI.hasNext()) { + // There better only be one... + Vertex tmpVert = mvertI.next(); + String connectToType = + tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if ((connectToType != null) + && connectToType.equals("constrained-element-set")) { + // This is the "constrained-element-set" that we want to use as the + // Replacement + thisHash.put(uuidOfTheOneToBeReplaced, tmpVert); + } + } + } + return thisHash; + } else { + // Didn't find anything to add, so just return what they passed in. + return currentHash; + } + + } // End of getModConstraintHash() + + /** + * Gets the top element vertex for service or resource model. + * + * @param modelVerVtx the model-ver vertex + * @return first element pointed to by this model-ver + * @throws AAIException the AAI exception + */ + public Vertex getTopElementForSvcOrResModelVer(Vertex modelVerVtx, String trail) + throws AAIException { + + // For a "resource" or "service" type model, return the "top" element in that model + if (modelVerVtx == null) { + String msg = " null modelVertex passed to getTopoElementForSvcOrResModelVer() at [" + + trail + "]. "; + throw new AAIException("AAI_6114", msg); + } + + String modelVerId = modelVerVtx.<String>property("model-version-id").orElse(null); + if (modelVerId == null) { + String nt = modelVerVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if (nt != null && !nt.equals("model-ver")) { + String msg = "Illegal model defined: model element pointing to nodeType: [" + nt + + "], should be pointing to: [model-ver] at [" + trail + "]. "; + throw new AAIException("AAI_6132", msg); + } + } + + Vertex firstElementVertex = null; + + Iterator<Vertex> vertI = + this.traverseIncidentEdges(EdgeType.TREE, modelVerVtx, "model-element"); + int elCount = 0; + while (vertI != null && vertI.hasNext()) { + elCount++; + firstElementVertex = vertI.next(); + } + + if (elCount > 1) { + String msg = + "Illegal model defined: More than one first element defined for model-ver-id = " + + modelVerId + " at [" + trail + "]. "; + throw new AAIException("AAI_6132", msg); + } + + if (firstElementVertex == null) { + String msg = "Could not find first model element for model-ver-id = " + modelVerId + + " at [" + trail + "]. "; + throw new AAIException("AAI_6132", msg); + } + + return firstElementVertex; + + } // End of getTopElementForSvcOrResModelVer() + + /** + * Gets the named query prop over ride. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param namedQueryElementVertex the named query element vertex + * @param instanceVertex the instance vertex + * @param apiVer the api ver + * @return HashMap of alternate properties to return for this element + * @throws AAIException the AAI exception + */ + public Map<String, Object> getNamedQueryPropOverRide(String transId, String fromAppId, + Vertex namedQueryElementVertex, Vertex instanceVertex, String apiVer) throws AAIException { + + // If this model-element says that they want an alternative set of properties returned, then + // pull that + // data out of the instance vertex. + + Map<String, Object> altPropHash = new HashMap<>(); + + if (namedQueryElementVertex == null) { + String msg = " null namedQueryElementVertex passed to getNamedQueryPropOverRide() "; + throw new AAIException("AAI_6114", msg); + } + + List<String> propCollectList = new ArrayList<>(); + Iterator<VertexProperty<Object>> vpI = + namedQueryElementVertex.properties("property-collect-list"); + while (vpI.hasNext()) { + propCollectList.add((String) vpI.next().value()); + } + + for (int i = 0; i < propCollectList.size(); i++) { + String thisPropName = propCollectList.get(i); + Object instanceVal = instanceVertex.<Object>property(thisPropName).orElse(null); + altPropHash.put(thisPropName, instanceVal); + } + + return altPropHash; + + } // End of getNamedQueryPropOverRide() + + /** + * Named query constraint says stop. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param namedQueryElementVertex the named query element vertex + * @param instanceVertex the instance vertex + * @param apiVer the api ver + * @return true - if a constraint was defined that has not been met by the passed instanceVertex + * @throws AAIException the AAI exception + */ + public Boolean namedQueryConstraintSaysStop(String transId, String fromAppId, + Vertex namedQueryElementVertex, Vertex instanceVertex, String apiVer) throws AAIException { + + // For each (if any) property-constraint defined for this named-query-element, we will + // evaluate if + // the constraint is met or not-met. if there are constraints and any are not-met, then + // we return "true". + + if (namedQueryElementVertex == null) { + String msg = " null namedQueryElementVertex passed to namedQueryConstraintSaysStop() "; + throw new AAIException("AAI_6114", msg); + } + if (instanceVertex == null) { + String msg = " null instanceVertex passed to namedQueryConstraintSaysStop() "; + throw new AAIException("AAI_6114", msg); + } + + Iterator<Vertex> constrPipe = this.traverseIncidentEdges(EdgeType.TREE, + namedQueryElementVertex, "property-constraint"); + if (constrPipe == null || !constrPipe.hasNext()) { + // There's no "property-constraint" defined for this named-query-element. No problem. + return false; + } + + while (constrPipe.hasNext()) { + Vertex constrVtx = constrPipe.next(); + // We found a property constraint that we will need to check + String conType = constrVtx.<String>property("constraint-type").orElse(null); + if ((conType == null) || conType.equals("")) { + String msg = + " Bad property-constraint (constraint-type) found in Named Query definition. "; + throw new AAIException("AAI_6133", msg); + } + String propName = constrVtx.<String>property("property-name").orElse(null); + if ((propName == null) || propName.equals("")) { + String msg = + " Bad property-constraint (property-name) found in Named Query definition. "; + throw new AAIException("AAI_6133", msg); + } + String propVal = constrVtx.<String>property("property-value").orElse(null); + if ((propVal == null) || propVal.equals("")) { + String msg = " Bad property-constraint (propVal) found in Named Query definition. "; + throw new AAIException("AAI_6133", msg); + } + + // See if that constraint is met or not + String val = instanceVertex.<String>property(propName).orElse(null); + if (val == null) { + val = ""; + } + + if (conType.equals("EQUALS")) { + if (!val.equals(propVal)) { + // This constraint was not met + return true; + } + } else if (conType.equals("NOT-EQUALS")) { + if (val.equals(propVal)) { + // This constraint was not met + return true; + } + } else { + String msg = + " Bad property-constraint (constraint-type) found in Named Query definition. "; + throw new AAIException("AAI_6133", msg); + } + } + + return false; + + } // End of namedQueryConstraintSaysStop() + + /** + * Gets the named query extra data lookup. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param namedQueryElementVertex the named query element vertex + * @param instanceVertex the instance vertex + * @param apiVer the api ver + * @return HashMap of alternate properties to return for this element + * @throws AAIException the AAI exception + */ + public Map<String, Object> getNamedQueryExtraDataLookup(String transId, String fromAppId, + Vertex namedQueryElementVertex, Vertex instanceVertex, String apiVer) throws AAIException { + + // For each (if any) related-lookup defined for this named-query-element, we will go and + // and try to find it. All the related-lookup data will get put in a hash and returned. + + if (namedQueryElementVertex == null) { + String msg = " null namedQueryElementVertex passed to getNamedQueryExtraDataLookup() "; + throw new AAIException("AAI_6114", msg); + } + if (instanceVertex == null) { + String msg = " null instanceVertex passed to getNamedQueryExtraDataLookup() "; + throw new AAIException("AAI_6114", msg); + } + + Map<String, Object> retHash = new HashMap<>(); + + Iterator<Vertex> lookPipe = + this.traverseIncidentEdges(EdgeType.TREE, namedQueryElementVertex, "related-lookup"); + if (lookPipe == null || !lookPipe.hasNext()) { + // There's no "related-lookup" defined for this named-query-element. No problem. + return retHash; + } + + while (lookPipe.hasNext()) { + Vertex relLookupVtx = lookPipe.next(); + // We found a related-lookup record to try and use + String srcProp = relLookupVtx.<String>property("source-node-property").orElse(null); + String srcNodeType = relLookupVtx.<String>property("source-node-type").orElse(null); + srcProp = getPropNameWithAliasIfNeeded(srcNodeType, srcProp); + + if ((srcProp == null) || srcProp.equals("")) { + String msg = + " Bad related-lookup (source-node-property) found in Named Query definition. "; + throw new AAIException("AAI_6133", msg); + } + String targetNodeType = relLookupVtx.<String>property("target-node-type").orElse(null); + if ((targetNodeType == null) || targetNodeType.equals("")) { + String msg = + " Bad related-lookup (targetNodeType) found in Named Query definition. "; + throw new AAIException("AAI_6133", msg); + } + String targetProp = relLookupVtx.<String>property("target-node-property").orElse(null); + targetProp = getPropNameWithAliasIfNeeded(targetNodeType, targetProp); + + if ((targetProp == null) || targetProp.equals("")) { + String msg = + " Bad related-lookup (target-node-property) found in Named Query definition. "; + throw new AAIException("AAI_6133", msg); + } + + List<String> propCollectList = new ArrayList<>(); + Iterator<VertexProperty<Object>> vpI = relLookupVtx.properties("property-collect-list"); + while (vpI.hasNext()) { + propCollectList.add((String) vpI.next().value()); + } + + // Use the value from the source to see if we can find ONE target record using the + // value from the source + String valFromInstance = instanceVertex.<String>property(srcProp).orElse(null); + if (valFromInstance == null) { + // if there is no key to use to go look up something, we should end it here and just + // note what happened - no need to try to look something up by an empty key + logger.debug("WARNING - the instance data node of type [" + srcNodeType + + "] did not have a value for property [" + srcProp + + "], so related-lookup is being abandoned."); + return retHash; + } + + Map<String, Object> propHash = new HashMap<>(); + propHash.put(targetProp, valFromInstance); + + Optional<Vertex> result = dbMethHelper.locateUniqueVertex(targetNodeType, propHash); + if (!result.isPresent()) { + // If it can't find the lookup node, don't fail, just log that it couldn't be found + // --- logger.debug("WARNING - Could not find lookup node that corresponds to nodeType [" - + targetNodeType + "] propertyName = [" + srcProp - + "], propVal = [" + valFromInstance - + "] so related-lookup is being abandoned."); - return retHash; - } - else { - Vertex tmpVtx = result.get(); - // Pick up the properties from the target vertex that they wanted us to get - for( int j = 0; j < propCollectList.size(); j++ ){ - String tmpPropName = propCollectList.get(j); - tmpPropName = getPropNameWithAliasIfNeeded(targetNodeType, tmpPropName); - Object valObj = tmpVtx.<Object>property(tmpPropName).orElse(null); - String lookupKey = targetNodeType + "." + tmpPropName; - retHash.put(lookupKey, valObj); - - } - } - } - - return retHash; - - } // End of getNamedQueryExtraDataLookup() - - /** - * Collect NQ element hash. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param thisLevelElemVtx the element verrtx for this level - * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this nq-element vertex) from the top - * @param currentHash the current hash - * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point - * @param levelCounter the level counter - * @return HashMap of all widget-points on a namedQuery topology with the value being the "named-query-element-uuid" for that spot. - * @throws AAIException the AAI exception - */ - public Map<String, String> collectNQElementHash(String transId, String fromAppId, - Vertex thisLevelElemVtx, String incomingTrail, - Map<String,String> currentHash, List <String> vidsTraversed, - int levelCounter ) throws AAIException { - - levelCounter++; - - Map<String, String> thisHash = new HashMap<>(); - thisHash.putAll(currentHash); - - if( levelCounter > MAX_LEVELS ) { - throw new AAIException("AAI_6125", "collectNQElementHash() has looped across more levels than allowed: " + MAX_LEVELS + ". "); - } - String thisGuysTrail = ""; - String thisElemVid = thisLevelElemVtx.id().toString(); - - // Find out what widget (and thereby what aai-node-type) this element represents. - String thisElementNodeType = getNqElementWidgetType( transId, fromAppId, thisLevelElemVtx, incomingTrail ); - - if( incomingTrail == null || incomingTrail.equals("") ){ - // This is the first one - thisGuysTrail = thisElementNodeType; - } - else { - thisGuysTrail = incomingTrail + "|" + thisElementNodeType; - } - vidsTraversed.add(thisElemVid); - - String nqElementUuid = thisLevelElemVtx.<String>property("named-query-element-uuid").orElse(null); - if( nqElementUuid == null || nqElementUuid.equals("") ){ - String msg = " named-query element UUID not found at trail = [" + incomingTrail + "]."; - throw new AAIException("AAI_6133", msg); - } - thisHash.put(thisGuysTrail, nqElementUuid ); - - // Now go "down" and look at the sub-elements pointed to so we can get their data. - Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, thisLevelElemVtx, "named-query-element"); - while( vertI != null && vertI.hasNext() ){ - Vertex tmpVert = vertI.next(); - String vid = tmpVert.id().toString(); - Map<String,Object> elementHash = new HashMap(); - - String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( connectToType != null && connectToType.equals("named-query-element") ){ - // This is what we would expect - elementHash.put(vid, tmpVert); - } - else { - String msg = " named query element has [connectedTo] edge to improper nodeType= [" - + connectToType + "] trail = [" + incomingTrail + "]."; - throw new AAIException("AAI_6133", msg); - } - for( Map.Entry<String, Object> entry : elementHash.entrySet() ){ - Vertex elVert = (Vertex)(entry.getValue()); - String tmpElVid = elVert.id().toString(); - if( !vidsTraversed.contains(tmpElVid) ){ - // This is one we would like to use - so we'll recursively get it's result set to add to ours - Map<String, String> tmpHash = collectNQElementHash( transId, fromAppId, - elVert, thisGuysTrail, currentHash, vidsTraversed, levelCounter); - thisHash.putAll(tmpHash); - } - } - } - return thisHash; - - } // End of collectNQElementHash() - - - /** - * Collect delete key hash. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param thisLevelElemVtx the element vertex at this level - * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this vertex) from the top - * @param currentHash the current hash - * @param vidsTraversed the vids traversed ---- ArrayList of vertexId's that we traversed to get to this point - * @param levelCounter the level counter - * @param modConstraintHash the mod constraint hash - * @param overRideModelId the over ride model id - * @param overRideModelVersionId the over ride model version id - * @return HashMap of all widget-points on a model topology with the value being the "newDataDelFlag" for that spot. - * @throws AAIException the AAI exception - */ - public Map<String, String> collectDeleteKeyHash(String transId, String fromAppId, - Vertex thisLevelElemVtx, String incomingTrail, - Map<String,String> currentHash, List <String> vidsTraversed, - int levelCounter, Map<String, Vertex> modConstraintHash, - String overRideModelId, String overRideModelVersionId ) - throws AAIException { - - levelCounter++; - - Map<String, String> thisHash = new HashMap<>(); - thisHash.putAll(currentHash); - - if( levelCounter > MAX_LEVELS ) { - throw new AAIException("AAI_6125", "collectDeleteKeyHash() has looped across more levels than allowed: " + MAX_LEVELS + ". "); - } - String thisGuysTrail = ""; - String thisElemVid = thisLevelElemVtx.id().toString(); - Map<String, Vertex> modConstraintHash2Use = null; - - // If this element represents a resource or service model, then we will replace this element with - // the "top" element of that resource or service model. That model-element already points to its - // topology, so it will graft in that model's topology. - // EXCEPT - if this element has "linkage-points" defined, then we need to do some extra - // processing for how we join to that model and will not try to go any "deeper". - List<String> linkagePtList = new ArrayList<>(); - Iterator <VertexProperty<Object>> vpI = thisLevelElemVtx.properties("linkage-points"); - - // I am not sure why, but since "linkage-points" is an xml-element-wrapper in the OXM definition, - // we get back the whole array of Strings in one String - but still use the "vtx.properties()" to - // get it - but only look at the first thing returned by the iterator. - if( vpI.hasNext() ){ - String tmpLinkageThing = (String)vpI.next().value(); - linkagePtList = makeSureItsAnArrayList( tmpLinkageThing ); - } - - if( linkagePtList != null && !linkagePtList.isEmpty() ){ - // Whatever this element is - we are connecting to it via a linkage-point - // We will figure out what to do and then return without going any deeper - String elemFlag = thisLevelElemVtx.<String>property("new-data-del-flag").orElse(null); - - Set<String> linkageConnectNodeTypes = getLinkageConnectNodeTypes( linkagePtList ); - Iterator <?> linkNtIter = linkageConnectNodeTypes.iterator(); - String incTrail = ""; - if( incomingTrail != null && !incomingTrail.equals("") ){ - incTrail = incomingTrail + "|"; - } - - while( linkNtIter.hasNext() ){ - // The 'trail' (or trails) for this element should just be the to the first-contact on the linkage point - String linkTrail = incTrail + linkNtIter.next(); - Boolean alreadyTaggedFalse = false; - if( thisHash.containsKey(linkTrail) && thisHash.get(linkTrail).equals("F") ){ - // some other path with a matching trail has the deleteFlag set to "F", so we do not want - // to override that since our model code only uses nodeTypes to know where it is - and we - // would rather do less deleting than needed instead of too much deleting. - alreadyTaggedFalse = true; - } - if( elemFlag != null && elemFlag.equals("T") && !alreadyTaggedFalse ){ - // This trail should be marked with an "T" - thisHash.put(linkTrail, "T"); - } - else { - thisHash.put(linkTrail, "F"); - } - } - return thisHash; - } - - // ---------------------------------------------------------------------------- - // If we got to here, then this was not an element that used a linkage-point - // ---------------------------------------------------------------------------- - - // Find out what widget-model (and thereby what aai-node-type) this element represents. - // Even if this element is pointing to a service or resource model, it must have a - // first element which is a single widget-type model. - String thisElementNodeType = getModElementWidgetType( thisLevelElemVtx, incomingTrail ); - String firstElementModelInfo = ""; - - vidsTraversed.add(thisElemVid); - Vertex elementVtxForThisLevel = null; - Vertex thisElementsModelVerVtx = getModelVerThatElementRepresents( thisLevelElemVtx, incomingTrail ); - Vertex thisElementsModelVtx = getModelGivenModelVer( thisElementsModelVerVtx, incomingTrail ); - String modType = getModelTypeFromModel( thisElementsModelVtx, incomingTrail ); - String subModelFirstModInvId = thisElementsModelVtx.<String>property("model-invariant-id").orElse(null); - String subModelFirstVerId = thisElementsModelVerVtx.<String>property("model-version-id").orElse(null); - if( modType.equals("widget") ){ - if( overRideModelId != null && !overRideModelId.equals("") ){ - // Note - this is just to catch the correct model for the TOP node in a model since - // it will have an element which will always be a widget even though the model - // could be a resource or service model. - firstElementModelInfo = "," + overRideModelId + "," + overRideModelVersionId; - } - } - else if( nodeTypeSupportsPersona(thisElementNodeType) ){ - firstElementModelInfo = "," + subModelFirstModInvId + "," + subModelFirstVerId; - } - - if( incomingTrail.equals("") ){ - // This is the first one - thisGuysTrail = thisElementNodeType + firstElementModelInfo; - } - else { - thisGuysTrail = incomingTrail + "|" + thisElementNodeType + firstElementModelInfo; - } - - String tmpFlag = "F"; - Boolean stoppedByASvcOrResourceModelElement = false; - if( modType.equals("widget") ){ - elementVtxForThisLevel = thisLevelElemVtx; - // For the element-model for the widget at this level, record it's delete flag - tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null); - } - else { - // For an element that is referring to a resource or service model, we replace - // this element with the "top" element for that resource/service model so that the - // topology of that resource/service model will be included in this topology. - String modelVerId = thisElementsModelVerVtx.<String>property("model-version-id").orElse(null); - if( subModelFirstModInvId == null || subModelFirstModInvId.equals("") - || subModelFirstVerId == null || subModelFirstVerId.equals("") ){ - throw new AAIException("AAI_6132", "Bad Model Definition: Bad model-invariant-id or model-version-id. Model-version-id = " + - modelVerId + ", at [" + incomingTrail + "]"); - } - - // BUT -- if the model-element HERE at the resource/service level does NOT have - // it's new-data-del-flag set to "T", then we do not need to go down into the - // sub-model looking for delete-able things. - - tmpFlag = thisLevelElemVtx.<String>property("new-data-del-flag").orElse(null); - elementVtxForThisLevel = getTopElementForSvcOrResModelVer(thisElementsModelVerVtx, thisGuysTrail); - if( tmpFlag != null && tmpFlag.equals("T") ){ - modConstraintHash2Use = getModConstraintHash( thisLevelElemVtx, modConstraintHash ); - } - else { - stoppedByASvcOrResourceModelElement = true; - } - // For the element-model for the widget at this level, record it's delete flag - tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null); - } - - String flag2Use = "F"; // by default we'll use "F" for the delete flag - if( ! stoppedByASvcOrResourceModelElement ){ - // Since we haven't been stopped by a resource/service level "F", we can look at the lower level flag - if( thisHash.containsKey(thisGuysTrail) ){ - // We've seen this spot in the topology before - do not override the delete flag if the older one is "F" - // We will only over-ride it if the old one was "T" and the new one is "F" (anything but "T") - String oldFlag = thisHash.get(thisGuysTrail); - if( oldFlag.equals("T") && (tmpFlag != null) && tmpFlag.equals("T") ){ - // The old flag was "T" and the new flag is also "T" - flag2Use = "T"; - } - else { - // the old flag was not "F" - so don't override it - flag2Use = "F"; - } - } - else if( (tmpFlag != null) && tmpFlag.equals("T") ){ - // We have not seen this one, so we can set it to "T" if that's what it is. - flag2Use = "T"; - } - } - - thisHash.put(thisGuysTrail, flag2Use); - if( ! stoppedByASvcOrResourceModelElement ){ - // Since we haven't been stopped by a resource/service level "F", we will continue to - // go "down" and look at the elements pointed to so we can get their data. - Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, elementVtxForThisLevel, "model-element", "constrained-element-set"); - while( vertI != null && vertI.hasNext() ){ - Vertex tmpVert = vertI.next(); - String vid = tmpVert.id().toString(); - Map<String,Object> elementHash = new HashMap<>(); - - String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( connectToType != null && connectToType.equals("model-element") ){ - // A nice, regular old model-element - elementHash.put(vid, tmpVert); - } - else if( (connectToType != null) && connectToType.equals("constrained-element-set") ){ - // translate the constrained-element-set into a hash of model-element Vertex's - String constrainedElementSetUuid = tmpVert.<String>property("constrained-element-set-uuid").orElse(null); - if( (modConstraintHash2Use != null) && modConstraintHash2Use.containsKey(constrainedElementSetUuid) ){ - // This constrained-element-set is being superseded by a different one - Vertex replacementConstraintVert = modConstraintHash.get(constrainedElementSetUuid); - elementHash = getNextStepElementsFromSet( replacementConstraintVert ); - // Now that we've found and used the replacement constraint, we don't need to carry it along any farther - modConstraintHash.remove(constrainedElementSetUuid); - } - else { - elementHash = getNextStepElementsFromSet( tmpVert ); - } - } - else { - String msg = " model-element has [connectedTo] edge to improper nodeType= [" - + connectToType + "] trail = [" + incomingTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - for( Map.Entry<String, Object> entry : elementHash.entrySet() ){ - Vertex elVert = (Vertex)(entry.getValue()); - String tmpElVid = elVert.id().toString(); - String tmpElNT = getModElementWidgetType( elVert, thisGuysTrail ); - check4EdgeRule(tmpElNT, thisElementNodeType); - if( !vidsTraversed.contains(tmpElVid) ){ - // This is one we would like to use - so we'll recursively get it's result set to add to ours - Map<String, String> tmpHash = collectDeleteKeyHash( transId, fromAppId, - elVert, thisGuysTrail, - currentHash, vidsTraversed, levelCounter, modConstraintHash2Use, - "", "" ); - thisHash.putAll(tmpHash); - } - } - } - } - return thisHash; - - } // End of collectDeleteKeyHash() - - - /** - * Gets the linkage connect node types. - * - * @param linkagePtList the linkage pt list - * @return the linkage connect node types - * @throws AAIException the AAI exception - */ - public Set<String> getLinkageConnectNodeTypes(List<String> linkagePtList ) - throws AAIException { - // linkage points are a path from the top of a model to where we link in. - // This method wants to just bring back a list of distinct last items. - // Ie: for the input with these two: "pserver|lag-link|l-interface" and "pserver|p-interface|l-interface" - // it would just return a single item, "l-interface" since both linkage points end in that same node-type. - - Set<String> linkPtSet = new HashSet<>(); - - if( linkagePtList == null ){ - String detail = " Bad (null) linkagePtList passed to getLinkageConnectNodeTypes() "; - throw new AAIException("AAI_6125", detail); - } - - for( int i = 0; i < linkagePtList.size(); i++ ){ - String [] trailSteps = linkagePtList.get(i).split("\\|"); - if( trailSteps == null || trailSteps.length == 0 ){ - String detail = " Bad incomingTrail passed to getLinkageConnectNodeTypes(): [" + linkagePtList + "] "; - throw new AAIException("AAI_6125", detail); - } - String lastStepNT = trailSteps[trailSteps.length - 1]; - linkPtSet.add(lastStepNT); - } - - return linkPtSet; - - }// End getLinkageConnectNodeTypes() - - - /** - * Collect topology for model-ver. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param thisLevelElemVtx vertex to collect for - * @param incomingTrail the incoming trail -- trail of nodeTypes/personaInfo that got us here (this vertex) from the top - * @param currentMap the current map -- map that got us to this point (that we will use as the base of the map we will return) - * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point - * @param levelCounter the level counter - * @param modConstraintHash the mod constraint hash - * @param overRideModelInvId the override model-invariant-id - * @param overRideModelVersionId the override model-version-id - * @return Map of the topology - * @throws AAIException the AAI exception - */ - public Multimap<String, String> collectTopology4ModelVer(String transId, String fromAppId, - Vertex thisLevelElemVtx, String incomingTrail, - Multimap<String,String> currentMap, List<String> vidsTraversed, - int levelCounter, Map<String, Vertex> modConstraintHash, - String overRideModelInvId, String overRideModelVersionId ) - throws AAIException { - - levelCounter++; - - Multimap<String, String> thisMap = ArrayListMultimap.create(); - thisMap.putAll(currentMap); - - if( levelCounter > MAX_LEVELS ) { - throw new AAIException("AAI_6125", "collectTopology4ModelVer() has looped across more levels than allowed: " + MAX_LEVELS + ". "); - } - String thisGuysTrail = ""; - String thisElemVid = thisLevelElemVtx.id().toString(); - Map<String, Vertex> modConstraintHash2Use = null; - - // If this element represents a resource or service model, then we will replace this element with - // the "top" element of that resource or service model. That model-element already points to its - // topology, so it will graft in that model's topology. - // EXCEPT - if this element defines "linkage-points" defined, then we need to do some extra - // processing for how we join to that model. - - // Find out what widget-model (and thereby what aai-node-type) this element represents. - // Even if this element is pointing to a service or resource model, it must have a - // first element which is a single widget-type model. - String firstElementModelInfo = ""; - String thisElementNodeType = getModElementWidgetType( thisLevelElemVtx, incomingTrail ); - if( nodeTypeSupportsPersona(thisElementNodeType) && overRideModelInvId != null && !overRideModelInvId.equals("") ){ - firstElementModelInfo = "," + overRideModelInvId + "," + overRideModelVersionId; - } - - Vertex elementVtxForThisLevel = null; - Vertex thisElementsModelVerVtx = getModelVerThatElementRepresents( thisLevelElemVtx, incomingTrail ); - String subModelFirstModInvId = ""; - String subModelFirstModVerId = ""; - String modInfo4Trail = ""; - String modType = getModelTypeFromModelVer( thisElementsModelVerVtx, incomingTrail ); - if( modType.equals("resource") || modType.equals("service") ){ - // For an element that is referring to a resource or service model, we replace this - // this element with the "top" element for that resource/service model so that the - // topology of that resource/service model gets included in this topology. - // -- Note - since that top element of a service or resource model will point to a widget model, - // we have to track what modelId/version it really maps so we can make our recursive call - Vertex thisElementsModelVtx = getModelGivenModelVer(thisElementsModelVerVtx, incomingTrail); - subModelFirstModInvId = thisElementsModelVtx.<String>property("model-invariant-id").orElse(null); - subModelFirstModVerId = thisElementsModelVerVtx.<String>property("model-version-id").orElse(null); - - if( nodeTypeSupportsPersona(thisElementNodeType) ){ - modInfo4Trail = "," + subModelFirstModInvId + "," + subModelFirstModVerId; - } - String modelVerId = thisElementsModelVerVtx.<String>property("model-version-id").orElse(null); - if( subModelFirstModInvId == null || subModelFirstModInvId.equals("") || subModelFirstModVerId == null || subModelFirstModVerId.equals("") ){ - throw new AAIException("AAI_6132", "Bad Model Definition: Bad model-invariant-id or model-version-id. Model-ver-id = " + modelVerId); - } - - elementVtxForThisLevel = getTopElementForSvcOrResModelVer(thisElementsModelVerVtx, incomingTrail); - modConstraintHash2Use = getModConstraintHash( thisLevelElemVtx, modConstraintHash ); - } - else { - elementVtxForThisLevel = thisLevelElemVtx; - } - - if( incomingTrail.equals("") ){ - // This is the first one - thisGuysTrail = thisElementNodeType + firstElementModelInfo; - } - else { - thisGuysTrail = incomingTrail + "|" + thisElementNodeType + modInfo4Trail; - } - - // We only want to ensure that a particular element does not repeat on a single "branch". - // It could show up on other branches in the case where it is a sub-model which is being - // used in more than one place. - // - List<String> thisTrailsVidsTraversed = new ArrayList<>(vidsTraversed); - thisTrailsVidsTraversed.add(thisElemVid); - - // Look at the elements pointed to at this level and add on their data - Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, elementVtxForThisLevel, "model-element", "constrained-element-set"); - - while( vertI != null && vertI.hasNext() ){ - Vertex tmpVert = vertI.next(); - String vid = tmpVert.id().toString(); - Map<String,Object> elementHash = new HashMap<>(); - String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( connectToType != null && connectToType.equals("model-element") ){ - // A nice, regular old model-element - elementHash.put(vid, tmpVert); - } - else if( (connectToType != null) && connectToType.equals("constrained-element-set") ){ - // translate the constrained-element-set into a hash of model-element Vertex's - String constrainedElementSetUuid = tmpVert.<String>property("constrained-element-set-uuid").orElse(null); - if( (modConstraintHash2Use != null) && modConstraintHash2Use.containsKey(constrainedElementSetUuid) ){ - // This constrained-element-set is being superseded by a different one - Vertex replacementConstraintVert = modConstraintHash.get(constrainedElementSetUuid); - elementHash = getNextStepElementsFromSet( replacementConstraintVert ); - // Now that we've found and used the replacement constraint, we don't need to carry it along any farther - modConstraintHash.remove(constrainedElementSetUuid); - } - else { - elementHash = getNextStepElementsFromSet( tmpVert ); - } - } - else { - String msg = " model element has [connectedTo] edge to improper nodeType= [" - + connectToType + "] trail = [" + incomingTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - for( Map.Entry<String, Object> entry : elementHash.entrySet() ){ - Vertex elVert = (Vertex)(entry.getValue()); - String tmpElVid = elVert.id().toString(); - String tmpElNT = getModElementWidgetType( elVert, thisGuysTrail ); - String tmpElStepName = getModelElementStepName( elVert, thisGuysTrail); - - List<String> linkagePtList = new ArrayList <>(); - Iterator <VertexProperty<Object>> vpI = elVert.properties("linkage-points"); - - // I am not sure why, but since "linkage-points" is an xml-element-wrapper in the OXM definition, - // we get back the whole array of Strings in one String - but still use the "vtx.properties()" to - // get it - but only look at the first thing returned by the iterator. - if( vpI.hasNext() ){ - String tmpLinkageThing = (String)vpI.next().value(); - linkagePtList = makeSureItsAnArrayList( tmpLinkageThing ); - } - - if( linkagePtList != null && !linkagePtList.isEmpty() ){ - // This is as far as we can go, we will use the linkage point info to define the - // rest of this "trail" - for( int i = 0; i < linkagePtList.size(); i++ ){ - Multimap<String, String> tmpMap = collectTopology4LinkagePoint( transId, fromAppId, - linkagePtList.get(i), thisGuysTrail, currentMap); - thisMap.putAll(tmpMap); - } - } - else { - check4EdgeRule(tmpElNT, thisElementNodeType); - thisMap.put(thisGuysTrail, tmpElStepName); - if( !thisTrailsVidsTraversed.contains(tmpElVid) ){ - // This is one we would like to use - so we'll recursively get it's result set to add to ours - Multimap<String, String> tmpMap = collectTopology4ModelVer( transId, fromAppId, - elVert, thisGuysTrail, - currentMap, thisTrailsVidsTraversed, levelCounter, - modConstraintHash2Use, subModelFirstModInvId, subModelFirstModVerId ); - thisMap.putAll(tmpMap); - } - else { - String modelElementUuid = elVert.<String>property("model-element-uuid").orElse(null); - String msg = "Bad Model Definition: looping model-element (model-element-uuid = [" + - modelElementUuid + "]) found trying to add step: [" + tmpElStepName + "], " + - " on trail = [" + thisGuysTrail + "]. "; - System.out.println( msg ); - throw new AAIException("AAI_6132", msg); - } - } - } - } - - return thisMap; - - } // End of collectTopology4ModelVer() - - - /** - * Check 4 edge rule. - * - * @param nodeTypeA the node type A - * @param nodeTypeB the node type B - * @throws AAIException the AAI exception - */ - public void check4EdgeRule( String nodeTypeA, String nodeTypeB) throws AAIException { - // Throw an exception if there is no defined edge rule for this combination of nodeTypes in DbEdgeRules. - - final EdgeIngestor edgeRules = SpringContextAware.getApplicationContext().getBean(EdgeIngestor.class); - //final EdgeRules edgeRules = EdgeRules.getInstance(); - - EdgeRuleQuery.Builder baseQ = new EdgeRuleQuery.Builder(nodeTypeA, nodeTypeB); - if (!edgeRules.hasRule(baseQ.build())) { - - - /* if( !edgeRules.hasEdgeRule(nodeTypeA, nodeTypeB) - && !edgeRules.hasEdgeRule(nodeTypeB, nodeTypeA) ){*/ - // There's no EdgeRule for this -- find out if one of the nodeTypes is invalid or if - // they are valid, but there's just no edgeRule for them. - try { - loader.introspectorFromName(nodeTypeA); - } catch (AAIUnknownObjectException e) { - String emsg = " Unrecognized nodeType aa [" + nodeTypeA + "]\n"; - throw new AAIException("AAI_6115", emsg); - } - try { - loader.introspectorFromName(nodeTypeB); - } catch (AAIUnknownObjectException e) { - String emsg = " Unrecognized nodeType bb [" + nodeTypeB + "]\n"; - throw new AAIException("AAI_6115", emsg); - } - - String msg = " No Edge Rule found for this pair of nodeTypes (order does not matter) [" - + nodeTypeA + "], [" + nodeTypeB + "]."; - throw new AAIException("AAI_6120", msg); - } - - - } - - - /** - * Collect topology 4 linkage point. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param linkagePointStrVal -- Note it is in reverse order from where we connect to it. - * @param incomingTrail -- trail of nodeTypes that got us here (this vertex) from the top - * @param currentMap the current map -- that got us to this point (that we will use as the base of the map we will return) - * @return Map of the topology - * @throws AAIException the AAI exception - */ - public Multimap<String, String> collectTopology4LinkagePoint(String transId, String fromAppId, - String linkagePointStrVal, String incomingTrail, Multimap<String,String> currentMap) - throws AAIException { - - Multimap<String, String> thisMap = ArrayListMultimap.create(); - thisMap.putAll(currentMap); - String thisGuysTrail = incomingTrail; - - // NOTE - "trails" can have multiple parts now since we track persona info for some. - // We just want to look at the node type info - which would be the piece - // before any commas (if there are any). - - String [] trailSteps = thisGuysTrail.split("\\|"); - if(trailSteps.length == 0){ - throw new AAIException("AAI_6125", "Bad incomingTrail passed to collectTopology4LinkagePoint(): [" + incomingTrail + "] "); - } - String lastStepString = trailSteps[trailSteps.length - 1]; - String [] stepPieces = lastStepString.split(","); - String lastStepNT = stepPieces[0]; - - // It is assumed that the linkagePoint string will be a pipe-delimited string where each - // piece is an AAIProperties.NODE_TYPE. For now, the first thing to connect to is what is on the farthest right. - // Example: linkagePoint = "pserver|p-interface|l-interface" would mean that we're connecting to the l-interface - // but that after that, we connect to a p-interface followed by a pserver. - // It might have been more clear to define it in the other direction, but for now, that is it. (16-07) - String linkagePointStr = linkagePointStrVal; - - // We are getting these with more than linkage thing in one string. - // Ie. "pserver|lag-interface|l-interface, pserver|p-interface|l-interface, vlan|l-interface" - linkagePointStr = linkagePointStr.replace("[", ""); - linkagePointStr = linkagePointStr.replace("]", ""); - linkagePointStr = linkagePointStr.replace(" ", ""); - - String [] linkage = linkagePointStr.split("\\,"); - for( int x = 0; x < linkage.length; x++ ){ - lastStepNT = stepPieces[0]; - String thisStepNT = ""; - String [] linkageSteps = linkage[x].split("\\|"); - if(linkageSteps.length == 0){ - throw new AAIException("AAI_6125", "Bad linkagePointStr passed to collectTopology4LinkagePoint(): [" + linkagePointStr + "] "); - } - for( int i=(linkageSteps.length - 1); i >= 0; i-- ){ - thisStepNT = linkageSteps[i]; - check4EdgeRule(lastStepNT, thisStepNT); - thisMap.put(thisGuysTrail, thisStepNT); - thisGuysTrail = thisGuysTrail + "|" + thisStepNT; - lastStepNT = thisStepNT; - } - } - return thisMap; - - } // End of collectTopology4LinkagePoint() - - - /** - * Gets the next step elements from set. - * - * @param constrElemSetVtx the constr elem set vtx - * @return Hash of the set of model-elements this set represents - * @throws AAIException the AAI exception - */ - public Map<String,Object> getNextStepElementsFromSet( Vertex constrElemSetVtx ) - throws AAIException { - // Take a constrained-element-set and figure out the total set of all the possible elements that it - // represents and return them as a Hash. - - Map<String,Object> retElementHash = new HashMap<>(); - - if( constrElemSetVtx == null ){ - String msg = " getNextStepElementsFromSet() called with null constrElemSetVtx "; - throw new AAIException("AAI_6125", msg); - } - - String constrNodeType = constrElemSetVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); - String constrElemSetUuid = constrElemSetVtx.<String>property("constrained-element-set-uuid").orElse(null); - if( constrNodeType == null || !constrNodeType.equals("constrained-element-set") ){ - String msg = " getNextStepElementsFromSet() called with wrong type model: [" + constrNodeType + "]. "; - throw new AAIException("AAI_6125", msg); - } - - ArrayList <Vertex> choiceSetVertArray = new ArrayList<>(); - Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, constrElemSetVtx, "element-choice-set"); - int setCount = 0; - while( vertI != null && vertI.hasNext() ){ - Vertex choiceSetVertex = vertI.next(); - String constrSetType = choiceSetVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( constrSetType != null && constrSetType.equals("element-choice-set") ){ - choiceSetVertArray.add(choiceSetVertex); - setCount++; - } - } - - if( setCount == 0 ){ - String msg = "No element-choice-set found under constrained-element-set-uuid = " + constrElemSetUuid; - throw new AAIException("AAI_6132", msg); - } - - // Loop through each choice-set and grab the model-elements - for( int i = 0; i < setCount; i++ ){ - Vertex choiceSetVert = choiceSetVertArray.get(i); - Iterator<Vertex> mVertI = this.traverseIncidentEdges(EdgeType.TREE, choiceSetVert, "model-element"); - int elCount = 0; - while( mVertI != null && mVertI.hasNext() ){ - Vertex tmpElVertex = mVertI.next(); - String elNodeType = tmpElVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( elNodeType != null && elNodeType.equals("model-element") ){ - String tmpVid = tmpElVertex.id().toString(); - retElementHash.put(tmpVid, tmpElVertex); - elCount++; - } - else { - // unsupported node type found for this choice-set - String msg = "Unsupported nodeType (" + elNodeType - + ") found under choice-set under constrained-element-set-uuid = " + constrElemSetUuid; - throw new AAIException("AAI_6132", msg); - } - } - - if( elCount == 0 ){ - String msg = "No model-elements found in choice-set under constrained-element-set-uuid = " + constrElemSetUuid; - throw new AAIException("AAI_6132", msg); - } - - } - return retElementHash; - - } // End of getNextStepElementsFromSet() - - - - /** - * Gen topo map 4 named Q. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param queryVertex the query vertex - * @param namedQueryUuid the named query uuid - * @return MultiMap of valid next steps for each potential query-element - * @throws AAIException the AAI exception - */ - public Multimap<String, String> genTopoMap4NamedQ(String transId, String fromAppId, - Vertex queryVertex, String namedQueryUuid ) - throws AAIException { - - if( queryVertex == null ){ - throw new AAIException("AAI_6125", "null queryVertex passed to genTopoMap4NamedQ()"); - } - - Multimap<String, String> initialEmptyMap = ArrayListMultimap.create(); - List<String> vidsTraversed = new ArrayList<>(); - - Vertex firstElementVertex = null; - Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, queryVertex, "named-query-element"); - int elCount = 0; - while( vertI != null && vertI.hasNext() ){ - elCount++; - firstElementVertex = vertI.next(); - } - - if( elCount > 1 ){ - throw new AAIException("AAI_6133", "Illegal query defined: More than one first element defined for = " + namedQueryUuid); - } - - if( firstElementVertex == null ){ - throw new AAIException("AAI_6114", "Could not find first query element = " + namedQueryUuid); - } - - Vertex modVtx = getModelThatNqElementRepresents( firstElementVertex, "" ); - String modelType = getModelTypeFromModel( modVtx, "" ); - if( ! modelType.equals("widget") ){ - throw new AAIException("AAI_6133", "Bad Named Query Definition: First element must correspond to a widget type model. Named Query UUID = " - + namedQueryUuid); - } - - return collectTopology4NamedQ( transId, fromAppId, - firstElementVertex, "", - initialEmptyMap, vidsTraversed, 0); - } // End of genTopoMap4NamedQ() - - - - /** - * Collect topology 4 named Q. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param thisLevelElemVtx the model element vertex for this level - * @param levelCounter the level counter - * @return resultSet - * @throws AAIException the AAI exception - */ - public Multimap<String, String> collectTopology4NamedQ(String transId, String fromAppId, - Vertex thisLevelElemVtx, String incomingTrail, - Multimap<String,String> currentMap, List<String> vidsTraversed, int levelCounter ) - throws AAIException { - - levelCounter++; - - Multimap<String, String> thisMap = ArrayListMultimap.create(); - thisMap.putAll(currentMap); - - String thisElemVid = thisLevelElemVtx.id().toString(); - if( levelCounter > MAX_LEVELS ) { - throw new AAIException("AAI_6125", "collectModelStructure() has looped across more levels than allowed: " + MAX_LEVELS + ". "); - } - String thisGuysTrail = ""; - - // find out what widget (and thereby what aai-node-type) this element represents - String thisElementNodeType = getNqElementWidgetType( transId, fromAppId, thisLevelElemVtx, incomingTrail ); - - if( incomingTrail.equals("") ){ - // This is the first one - thisGuysTrail = thisElementNodeType; - } - else { - thisGuysTrail = incomingTrail + "|" + thisElementNodeType; - } - - vidsTraversed.add(thisElemVid); - - // Look at the elements pointed to at this level and add on their data - Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, thisLevelElemVtx, "named-query-element"); - while( vertI != null && vertI.hasNext() ){ - Vertex tmpVert = vertI.next(); - String tmpVid = tmpVert.id().toString(); - String tmpElNT = getNqElementWidgetType( transId, fromAppId, tmpVert, thisGuysTrail ); - thisMap.put(thisGuysTrail, tmpElNT); - if( !vidsTraversed.contains(tmpVid) ){ - // This is one we would like to use - so we'll recursively get it's result set to add to ours - Multimap<String, String> tmpMap = collectTopology4NamedQ( transId, fromAppId, - tmpVert, thisGuysTrail, - currentMap, vidsTraversed, levelCounter); - thisMap.putAll(tmpMap); - } - } - - return thisMap; - - } // End of collectTopology4NamedQ() - - - /** - * Gets the model that NamedQuery element represents. - * - * @param elementVtx the NQ element vtx - * @param elementTrail the element trail - * @return the model that element represents - * @throws AAIException the AAI exception - */ - public Vertex getModelThatNqElementRepresents(Vertex elementVtx, String elementTrail ) - throws AAIException { - - // Get the model that a named-query element represents - Vertex modVtx = null; - Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.COUSIN, elementVtx, "model"); - int modCount = 0; - while( mvertI != null && mvertI.hasNext() ){ - modCount++; - modVtx = mvertI.next(); - } - - if( modCount > 1 ){ - String msg = "Illegal element defined: More than one model pointed to by a single named-query-element at [" + - elementTrail + "]."; - throw new AAIException("AAI_6125", msg); - } - - if( modVtx == null ){ - String msg = "Bad named-query definition: Could not find model for element. "; - if( !elementTrail.equals("") ){ - msg = "Bad named-query definition: Could not find model for named-query-element at [" + elementTrail + "]."; - } - throw new AAIException("AAI_6132", msg); - } - - String nodeType = modVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( (nodeType != null) && nodeType.equals("model") ){ - return modVtx; - } - else { - String msg = "Illegal Named Query element defined: expecting a 'model', but found 'isA' edge pointing to nodeType = " + - nodeType + "] at [" + elementTrail + "]."; - throw new AAIException("AAI_6125", msg); - } - - }// getModelThatNqElementRepresents() - - - /** - * Gets the model-ver that element represents. - * - * @param elementVtx the element vtx - * @param elementTrail the element trail - * @return the model-ver that element represents - * @throws AAIException the AAI exception - */ - public Vertex getModelVerThatElementRepresents(Vertex elementVtx, String elementTrail ) - throws AAIException { - - // Get the model-ver that an element represents - Vertex modVerVtx = null; - Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.COUSIN, elementVtx, "model-ver"); - int modCount = 0; - while( mvertI != null && mvertI.hasNext() ){ - modCount++; - modVerVtx = mvertI.next(); - } - - if( modCount > 1 ){ - String msg = "Illegal element defined: More than one model pointed to by a single element at [" + - elementTrail + "]."; - throw new AAIException("AAI_6125", msg); - } - - if( modVerVtx == null ){ - String msg = "Bad model definition: Could not find model-ver for model-element. "; - if( !elementTrail.equals("") ){ - msg = "Bad model definition: Could not find model-VER for model-element at [" + elementTrail + "]."; - } - throw new AAIException("AAI_6132", msg); - } - - String nodeType = modVerVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( (nodeType != null) && nodeType.equals("model-ver") ){ - return modVerVtx; - } - else { - String msg = "Illegal model-element defined: expecting a 'model-ver', but found 'isA' edge pointing to nodeType = " + - nodeType + "] at [" + elementTrail + "]."; - throw new AAIException("AAI_6125", msg); - } - - }// getModelVerThatElementRepresents() - - - - /** - * Gets the model that is parent to model-ver node. - * - * @param modVerVtx the model-ver vtx - * @param elementTrail the element trail - * @return the model that element represents - * @throws AAIException the AAI exception - */ - public Vertex getModelGivenModelVer(Vertex modVerVtx, String elementTrail ) - throws AAIException { - - // Get the parent model for this "model-ver" node - Vertex modVtx = null; - Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.TREE, modVerVtx, "model"); - int modCount = 0; - while( mvertI != null && mvertI.hasNext() ){ - modCount++; - modVtx = mvertI.next(); - } - - if( modCount > 1 ){ - String msg = "Illegal model-ver node defined: More than one model points to it with a 'has' edge [" + - elementTrail + "]."; - throw new AAIException("AAI_6125", msg); - } - - if( modVtx == null ){ - String msg = "Bad model-ver node: Could not find parent model. "; - if( !elementTrail.equals("") ){ - msg = "Bad model-ver node: Could not find parent model. [" + elementTrail + "]."; - } - throw new AAIException("AAI_6132", msg); - } - - String nodeType = modVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); - if( (nodeType != null) && nodeType.equals("model") ){ - // Found what we were looking for. - return modVtx; - } - else { - // Something is amiss - String msg = " Could not find parent model node for model-ver node at [" + - elementTrail + "]."; - throw new AAIException("AAI_6125", msg); - } - - - }// getModelGivenModelVer() - - - - /** - * Gets the model type. - * - * @param modelVtx the model vtx - * @param elementTrail the element trail - * @return the model type - * @throws AAIException the AAI exception - */ - public String getModelTypeFromModel(Vertex modelVtx, String elementTrail ) - throws AAIException { - - // Get the model-type from a model vertex - if( modelVtx == null ){ - String msg = " null modelVtx passed to getModelTypeFromModel() "; - throw new AAIException("AAI_6114", msg); - } - - String modelType = modelVtx.<String>property("model-type").orElse(null); - if( (modelType == null) || modelType.equals("") ){ - String msg = "Could not find model-type for model encountered at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - if( !modelType.equals("widget") && !modelType.equals("resource") && !modelType.equals("service") ){ - String msg = "Unrecognized model-type, [" + modelType + "] for model pointed to by element at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - return modelType; - - }// getModelTypeFromModel() - - - - /** - * Gets the model type given model-ver - * - * @param modelVerVtx the model-ver vtx - * @param elementTrail the element trail - * @return the model type - * @throws AAIException the AAI exception - */ - public String getModelTypeFromModelVer(Vertex modelVerVtx, String elementTrail ) - throws AAIException { - - // Get the model-type given a model-ver vertex - if( modelVerVtx == null ){ - String msg = " null modelVerVtx passed to getModelTypeFromModelVer() "; - throw new AAIException("AAI_6114", msg); - } - - Vertex modVtx = getModelGivenModelVer( modelVerVtx, elementTrail ); - String modelType = modVtx.<String>property("model-type").orElse(null); - if( (modelType == null) || modelType.equals("") ){ - String msg = "Could not find model-type for model encountered at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - if( !modelType.equals("widget") && !modelType.equals("resource") && !modelType.equals("service") ){ - String msg = "Unrecognized model-type, [" + modelType + "] for model pointed to by element at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - return modelType; - - }// getModelTypeFromModelVer() - - - - /** - * Gets the model-element step name. - * - * @param elementVtx the model-element vtx - * @param elementTrail the element trail - * @return the element step name - * @throws AAIException the AAI exception - */ - public String getModelElementStepName(Vertex elementVtx, String elementTrail) - throws AAIException { - - // Get the "step name" for a model-element - // Step names look like this for widget-models: AAIProperties.NODE_TYPE - // Step names look like this for resource/service models: "aai-node-type,model-invariant-id,model-version-id" - // NOTE -- if the element points to a resource or service model, then we'll return the - // widget-type of the first element (crown widget) for that model. - String thisElementNodeType = "?"; - Vertex modVerVtx = getModelVerThatElementRepresents( elementVtx, elementTrail ); - String modelType = getModelTypeFromModelVer( modVerVtx, elementTrail ); - - if( modelType == null ){ - String msg = " could not determine modelType in getModelElementStepName(). elementTrail = [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - if( modelType.equals("widget") ){ - // NOTE: for models that have model-type = "widget", their "model-name" maps directly to aai-node-type - thisElementNodeType = modVerVtx.<String>property("model-name").orElse(null); - if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){ - String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - return thisElementNodeType; - } - else if( modelType.equals("resource") || modelType.equals("service") ){ - Vertex modVtx = getModelGivenModelVer( modVerVtx, elementTrail ); - String modInvId = modVtx.<String>property("model-invariant-id").orElse(null); - String modVerId = modVerVtx.<String>property("model-version-id").orElse(null); - Vertex relatedTopElementModelVtx = getTopElementForSvcOrResModelVer( modVerVtx, elementTrail ); - Vertex relatedModelVtx = getModelVerThatElementRepresents( relatedTopElementModelVtx, elementTrail ); - thisElementNodeType = relatedModelVtx.<String>property("model-name").orElse(null); - - if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){ - String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - String stepName = ""; - if( nodeTypeSupportsPersona(thisElementNodeType) ){ - // This nodeType that this resource or service model refers to does support persona-related fields, so - // we will use model-invariant-id and model-version-id as part of the step name. - stepName = thisElementNodeType + "," + modInvId + "," + modVerId; - } - else { - stepName = thisElementNodeType; - } - return stepName; - } - else { - String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - }// getModelElementStepName() - - - - /** - * Node type supports persona. - * - * @param nodeType the node type - * @return the boolean - * @throws AAIException the AAI exception - */ - public Boolean nodeTypeSupportsPersona(String nodeType) - throws AAIException { - - if( nodeType == null || nodeType.equals("") ){ - return false; - } - Introspector introspector = null; - try { - introspector = loader.introspectorFromName(nodeType); - } catch (AAIUnknownObjectException e) { - String emsg = " Unrecognized nodeType [" + nodeType + "]\n"; - throw new AAIException("AAI_6115", emsg); - } - - Collection <String> props4ThisNT = introspector.getProperties(); - return props4ThisNT.contains(addDBAliasedSuffix("model-invariant-id")) && props4ThisNT.contains(addDBAliasedSuffix("model-version-id")); - - }// nodeTypeSupportsPersona() - - - /** - * Gets a Named Query element's widget type. - * - * @param elementVtx the named-query element vtx - * @param elementTrail the element trail - * @return the element widget type - * @throws AAIException the AAI exception - */ - public String getNqElementWidgetType(String transId, String fromAppId, - Vertex elementVtx, String elementTrail ) - throws AAIException { - - String thisNqElementWidgetType = ""; - // Get the associated node-type for the model pointed to by a named-query-element. - // NOTE -- if the element points to a resource or service model, then we'll return the - // widget-type of the first element (crown widget) for that model. - Vertex modVtx = getModelThatNqElementRepresents( elementVtx, elementTrail ); - String modelType = getModelTypeFromModel( modVtx, elementTrail ); - - if( modelType == null || !modelType.equals("widget") ){ - String emsg = " Model Type must be 'widget' for NamedQuery elements. Found [" + modelType + "] at [" + - elementTrail + "]\n"; - throw new AAIException("AAI_6132", emsg); - } - else { - // For a Widget model, the nodeType is just mapped to the model-element.model-name - List<Vertex> modVerVtxArr = getModVersUsingModel(transId, fromAppId, modVtx); - if( modVerVtxArr != null && !modVerVtxArr.isEmpty() ){ - thisNqElementWidgetType = (modVerVtxArr.get(0)).<String>property("model-name").orElse(null); - } - if( thisNqElementWidgetType == null || thisNqElementWidgetType.equals("") ){ - String emsg = " Widget type could not be determined at [" + elementTrail + "]\n"; - throw new AAIException("AAI_6132", emsg); - } - else { - return thisNqElementWidgetType; - } - } - - - }// End getNqElementWidgetType() - - - /** - * Gets a model-element's top widget type. - * - * @param elementVtx the model element vtx - * @param elementTrail the element trail - * @return the element widget type - * @throws AAIException the AAI exception - */ - public String getModElementWidgetType(Vertex elementVtx, String elementTrail ) - throws AAIException { - - // Get the associated node-type for the model-ver pointed to by a model-element. - // NOTE -- if the element points to a resource or service model, then we'll return the - // widget-type of the first element (crown widget) for that model. - Vertex modVerVtx = getModelVerThatElementRepresents( elementVtx, elementTrail ); - return getModelVerTopWidgetType( modVerVtx, elementTrail ); - - }// End getModElementWidgetType() - - - /** - * Gets the node using unique identifier - * - * @param transId the trans id - * @param fromAppId the from app id - * @param nodeType the nodeType - * @param idPropertyName the property name of the unique identifier - * @param uniqueIdVal the UUID value - * @return unique vertex found using UUID - * @throws AAIException the AAI exception - */ - public Vertex getNodeUsingUniqueId(String transId, String fromAppId, - String nodeType, String idPropertyName, String uniqueIdVal ) - throws AAIException { - - // Given a unique identifier, get the Vertex - if( uniqueIdVal == null || uniqueIdVal.equals("") ){ - String emsg = " Bad uniqueIdVal passed to getNodeUsingUniqueId(): [" - + uniqueIdVal + "]\n"; - throw new AAIException("AAI_6118", emsg); - } - - if( idPropertyName == null || idPropertyName.equals("") ){ - String emsg = " Bad idPropertyName passed to getNodeUsingUniqueId(): [" - + idPropertyName + "]\n"; - throw new AAIException("AAI_6118", emsg); - } - - if( nodeType == null || nodeType.equals("") ){ - String emsg = " Bad nodeType passed to getNodeUsingUniqueId(): [" - + nodeType + "]\n"; - throw new AAIException("AAI_6118", emsg); - } - - Vertex uniqVtx = null; - Iterable <?> uniqVerts = null; - uniqVerts = engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,nodeType).has(idPropertyName,uniqueIdVal).toList(); - if( uniqVerts == null ){ - String emsg = "Node could not be found for nodeType = [" + nodeType - + "], propertyName = [" + idPropertyName - + "], propertyValue = [" + uniqueIdVal + "]\n"; - throw new AAIException("AAI_6114", emsg); - } - else { - int count = 0; - Iterator <?> uniqVertsIter = uniqVerts.iterator(); - if( !uniqVertsIter.hasNext() ){ - String emsg = "Node could not be found for nodeType = [" + nodeType - + "], propertyName = [" + idPropertyName - + "], propertyValue = [" + uniqueIdVal + "]\n"; - throw new AAIException("AAI_6114", emsg); - } - else { - while( uniqVertsIter.hasNext() ){ - count++; - uniqVtx = (Vertex) uniqVertsIter.next(); - if( count > 1 ){ - String emsg = "More than one node found for nodeType = [" + nodeType - + "], propertyName = [" + idPropertyName - + "], propertyValue = [" + uniqueIdVal + "]\n"; - throw new AAIException("AAI_6132", emsg); - } - } - } - } - - return uniqVtx; - }// End getNodeUsingUniqueId() - - - /** - * Gets the model-ver nodes using name. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modelName the model name - * @return the model-ver's that use this name - * @throws AAIException the AAI exception - */ - public List<Vertex> getModelVersUsingName(String transId, String fromAppId, - String modelName ) - throws AAIException { - - // Given a "model-name", find the model-ver vertices that this maps to - if( modelName == null || modelName.equals("") ){ - String emsg = " Bad modelName passed to getModelVersUsingName(): [" - + modelName + "]\n"; - throw new AAIException("AAI_6118", emsg); - } - - List<Vertex> retVtxArr = new ArrayList<>(); - Iterator<Vertex> modVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-name",modelName); - if( !modVertsIter.hasNext() ){ - String emsg = "Model-ver record(s) could not be found for model-ver data passed. model-name = [" + - modelName + "]\n"; - throw new AAIException("AAI_6132", emsg); - } - else { - while( modVertsIter.hasNext() ){ - Vertex tmpModelVerVtx = modVertsIter.next(); - retVtxArr.add(tmpModelVerVtx); - } - } - - return retVtxArr; - - }// End getModelVersUsingName() - - - /** - * Gets the model-ver nodes using model-invariant-id. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modelInvId-invariant-id (uniquely identifies a model) - * @return the model-ver's defined for the corresponding model - * @throws AAIException the AAI exception - */ - public Iterator<Vertex> getModVersUsingModelInvId(String transId, String fromAppId, - String modelInvId ) - throws AAIException { - - // Given a "model-invariant-id", find the model-ver nodes that this maps to - if( modelInvId == null || modelInvId.equals("") ){ - String emsg = " Bad model-invariant-id passed to getModVersUsingModelInvId(): [" - + modelInvId + "]\n"; - throw new AAIException("AAI_6118", emsg); - } - - Vertex modVtx = getNodeUsingUniqueId(transId, fromAppId, "model", "model-invariant-id", modelInvId); - List<Vertex> retVtxArr = getModVersUsingModel(transId, fromAppId, modVtx); - if( retVtxArr == null || retVtxArr.isEmpty() ){ - String emsg = " Model-ver record(s) could not be found attached to model with model-invariant-id = [" + - modelInvId + "]\n"; - throw new AAIException("AAI_6132", emsg); - } - - return retVtxArr.iterator(); - }// End getModVersUsingModelInvId() - - - /** - * Gets the model-ver nodes using a model node. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modVtx vertex - * @return the model-ver's defined for the corresponding model - * @throws AAIException the AAI exception - */ - public List<Vertex> getModVersUsingModel(String transId, String fromAppId, - Vertex modVtx ) - throws AAIException { - - if( modVtx == null ){ - String emsg = " Null model vertex passed to getModVersUsingModel(): "; - throw new AAIException("AAI_6118", emsg); - } - - List<Vertex> retVtxArr = new ArrayList<>(); - Iterator<Vertex> modVerVertsIter = this.traverseIncidentEdges(EdgeType.TREE, modVtx, "model-ver"); - if(!modVerVertsIter.hasNext()){ - String modelInvId = modVtx.<String>property("model-invariant-id").orElse(null); - String emsg = "Model-ver record(s) could not be found attached to model with model-invariant-id = [" + - modelInvId + "]\n"; - throw new AAIException("AAI_6132", emsg); - } - else { - while( modVerVertsIter.hasNext() ){ - Vertex tmpModelVtx = modVerVertsIter.next(); - retVtxArr.add(tmpModelVtx); - } - } - - return retVtxArr; - - }// End getModVersUsingModel() - - /** - * Gets the model-version-ids using model-name. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modelName the model name - * @return the model uuids using name - * @throws AAIException the AAI exception - */ - public List<String> getModelVerIdsUsingName( String transId, String fromAppId, - String modelName ) - throws AAIException { - - // Given a model-name find the model-ver nodes that it maps to - if( modelName == null || modelName.equals("") ){ - String emsg = " Bad modelName passed to getModelVerIdsUsingName(): [" - + modelName + "]\n"; - throw new AAIException("AAI_6118", emsg); - } - - List<String> retArr = new ArrayList<>(); - Iterator<Vertex> modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-name",modelName); - if( !modVerVertsIter.hasNext() ){ - String emsg = " model-ver record(s) could not be found for model data passed. model-name = [" + - modelName + "]\n"; - throw new AAIException("AAI_6114", emsg); - } - else { - while( modVerVertsIter.hasNext() ){ - Vertex modelVerVtx = modVerVertsIter.next(); - String tmpUuid = modelVerVtx.<String>property("model-version-id").orElse(null); - if( (tmpUuid != null) && !tmpUuid.equals("") && !retArr.contains(tmpUuid) ){ - retArr.add(tmpUuid); - } - } - } - - if( retArr.isEmpty() ){ - String emsg = "No model-ver record found for model-name = [" - + modelName + "]\n"; - throw new AAIException("AAI_6132", emsg); - } - - return retArr; - }// End getModelVerIdsUsingName() - - - /** - * Gets the model top widget type. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modelVersionId the model-version-id - * @param modelInvId the model-invariant-id - * @param modelName the model-name - * @return the model top widget type - * @throws AAIException the AAI exception - */ - public String getModelVerTopWidgetType( String transId, String fromAppId, - String modelVersionId, String modelInvId, String modelName ) - throws AAIException { - - // Could be given a model-ver's key info (model-version-id), OR, just a (non-unique) model-name, - // Or just a model-invariant-id (which could have multiple model-ver records under it). - // In any case, they should only map to one single "top" node-type for the first element. - - String nodeType = "?"; - Iterator<Vertex> modVerVertsIter; - - if( modelVersionId != null && !modelVersionId.equals("") ){ - // this would be the best - we can just look up the model-ver records directly - modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-version-id",modelVersionId); - } - else if( modelName != null && !modelName.equals("") ){ - modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-name",modelName); - } - else if( modelInvId != null && !modelInvId.equals("") ){ - modVerVertsIter = getModVersUsingModelInvId(transId, fromAppId, modelInvId); - } - else { - String msg = "Neither modelVersionId, modelInvariantId, nor modelName passed to: getModelVerTopWidgetType() "; - throw new AAIException("AAI_6120", msg); - } - - if( !modVerVertsIter.hasNext() ){ - String emsg = "model-ver record(s) could not be found for model data passed: modelInvariantId = [" + modelInvId + - "], modeVersionId = [" + modelVersionId + "], modelName = [" + modelName + "]\n"; - throw new AAIException("AAI_6114", emsg); - } - else { - String lastNT = ""; - if( !modVerVertsIter.hasNext() ){ - String emsg = "model-ver record(s) could not be found for model data passed: modelInvariantId = [" + modelInvId + - "], modeVersionId = [" + modelVersionId + "], modelName = [" + modelName + "]\n"; - throw new AAIException("AAI_6114", emsg); - } - while( modVerVertsIter.hasNext() ){ - Vertex tmpModVerVtx = modVerVertsIter.next(); - String tmpNT = getModelVerTopWidgetType( tmpModVerVtx, "" ); - if( lastNT != null && !lastNT.equals("") ){ - if( !lastNT.equals(tmpNT) ){ - String emsg = "Different top-node-types (" + tmpNT + ", " + lastNT - + ") found for model data passed. (" + - " modelVersionId = [" + modelVersionId + - "], modelId = [" + modelInvId + - "], modelName = [" + modelName + - "])\n"; - throw new AAIException("AAI_6114", emsg); - } - } - lastNT = tmpNT; - nodeType = tmpNT; - } - } - - return nodeType; - - }// End getModelVerTopWidgetType() - - - /** - * Gets the widget type that this model-ver starts with. - * - * @param modVerVtx the model-version vtx - * @param elementTrail the element trail - * @return the widget type of the starting node of this model - * @throws AAIException the AAI exception - */ - public String getModelVerTopWidgetType(Vertex modVerVtx, String elementTrail ) - throws AAIException { - // Get the associated nodeType (Ie. aai-node-type / widget-type) for a model-ver. - // NOTE -- if the element points to a resource or service model, then we'll return the - // widget-type of the first element (crown widget) for that model. - String modelType = getModelTypeFromModelVer( modVerVtx, elementTrail ); - if( modelType == null ){ - String msg = " Could not determine modelType in getModelVerTopWidgetType(). elementTrail = [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - String thisElementNodeType = "?"; - if( modelType.equals("widget") ){ - // NOTE: for models that have model-type = "widget", their child model-ver nodes will - // have "model-name" which maps directly to aai-node-type (all model-ver's under one - // model should start with the same widget-type, so we only need to look at one). - thisElementNodeType = modVerVtx.<String>property("model-name").orElse(null); - if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){ - String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - } - else if( modelType.equals("resource") || modelType.equals("service") ){ - Vertex relatedTopElementVtx = getTopElementForSvcOrResModelVer( modVerVtx, elementTrail ); - Vertex relatedModVerVtx = getModelVerThatElementRepresents( relatedTopElementVtx, elementTrail ); - thisElementNodeType = relatedModVerVtx.<String>property("model-name").orElse(null); - if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){ - String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - } - else { - String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + elementTrail + "]."; - throw new AAIException("AAI_6132", msg); - } - - return thisElementNodeType; - - }// getModelVerTopWidgetType() - - - /** - * Validate model. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param modelVersionIdVal the model name version id - * @param apiVersion the api version - * @throws AAIException the AAI exception - */ - public void validateModel(String transId, String fromAppId, String modelVersionIdVal, String apiVersion ) - throws AAIException { - - // Note - this will throw an exception if the model either can't be found, or if - // we can't figure out its topology map. - Vertex modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", - "model-version-id", modelVersionIdVal); - if( modelVerVtx == null ){ - String msg = " Could not find model-ver with modelVersionId = [" + modelVersionIdVal + "]."; - throw new AAIException("AAI_6114", msg); - } - else { - Multimap<String, String> topoMap = genTopoMap4ModelVer( transId, fromAppId, - modelVerVtx, modelVersionIdVal); - String msg = " modelVer [" + modelVersionIdVal + "] topo multiMap looks like: \n[" + topoMap + "]"; - System.out.println("INFO -- " + msg ); - } - }// End validateModel() - - - /** - * Validate named query. - * - * @param transId the trans id - * @param fromAppId the from app id - * @param namedQueryUuid the named query uuid - * @param apiVersion the api version - * @throws AAIException the AAI exception - */ - public void validateNamedQuery(String transId, String fromAppId, String namedQueryUuid, String apiVersion ) - throws AAIException { - - // Note - this will throw an exception if the named query either can't be found, or if - // we can't figure out its topology map. - Vertex nqVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query", - "named-query-uuid", namedQueryUuid); - - if( nqVtx == null ){ - String msg = " Could not find named-query with namedQueryUuid = [" + namedQueryUuid + "]."; - throw new AAIException("AAI_6114", msg); - } - else { - //Multimap<String, String> topoMap = genTopoMap4NamedQ( "junkTransId", "junkFromAppId", - // graph, nqVtx, namedQueryUuid ); - //System.out.println("DEBUG -- for test only : --- "); - //System.out.println("DEBUG -- topomap = [" + topoMap + "]"); - } - - }// End validateNamedQuery() - - - /** - * Show result set. - * - * @param resSet the res set - * @param levelCount the level count - */ - public void showResultSet(ResultSet resSet, int levelCount ) { - - levelCount++; - String propsStr = ""; - for( int i= 1; i <= levelCount; i++ ){ - propsStr = propsStr + "-"; - } - if( resSet.getVert() == null ){ - return; - } - String nt = resSet.getVert().<String>property(AAIProperties.NODE_TYPE).orElse(null); - propsStr = propsStr + "[" + nt + "] "; - - //propsStr = propsStr + " newDataDelFlag = " + resSet.getNewDataDelFlag() + ", trail = " + resSet.getLocationInModelSubGraph(); - //propsStr = propsStr + "limitDesc = [" + resSet.getPropertyLimitDesc() + "]"; - propsStr = propsStr + " trail = " + resSet.getLocationInModelSubGraph(); - - Map<String,Object> overrideHash = resSet.getPropertyOverRideHash(); - if( overrideHash != null && !overrideHash.isEmpty() ){ - for( Map.Entry<String, Object> entry : overrideHash.entrySet() ){ - String propName = entry.getKey(); - Object propVal = entry.getValue(); - propsStr = propsStr + " [" + propName + " = " + propVal + "]"; - } - } - else { - Iterator<VertexProperty<Object>> pI = resSet.getVert().properties(); - while( pI.hasNext() ){ - VertexProperty<Object> tp = pI.next(); - if( ! tp.key().startsWith("aai") - && ! tp.key().equals("source-of-truth") - //&& ! tp.key().equals("resource-version") - && ! tp.key().startsWith("last-mod") - ) - { - propsStr = propsStr + " [" + tp.key() + " = " + tp.value() + "]"; - } - } - } - // Show the "extra" lookup values too - Map<String,Object> extraPropHash = resSet.getExtraPropertyHash(); - if( extraPropHash != null && !extraPropHash.isEmpty() ){ - for( Map.Entry<String, Object> entry : extraPropHash.entrySet() ){ - String propName = entry.getKey(); - Object propVal = entry.getValue(); - propsStr = propsStr + " [" + propName + " = " + propVal.toString() + "]"; - } - } - - System.out.println( propsStr ); - logger.info(propsStr); - - if( !resSet.getSubResultSet().isEmpty() ){ - ListIterator<ResultSet> listItr = resSet.getSubResultSet().listIterator(); - while( listItr.hasNext() ){ - showResultSet( listItr.next(), levelCount ); - } - } - - }// end of showResultSet() - - private Iterator<Vertex> traverseIncidentEdges(EdgeType treeType, Vertex startV, String connectedNodeType) throws AAIException { - return this.engine.getQueryBuilder(startV).createEdgeTraversal(treeType, startV, loader.introspectorFromName(connectedNodeType)); - } - - private Iterator<Vertex> traverseIncidentEdges(EdgeType treeType, Vertex startV, String... connectedNodeType) throws AAIException { - QueryBuilder[] builders = new QueryBuilder[connectedNodeType.length]; - for (int i = 0; i < connectedNodeType.length; i++) { - builders[i] = this.engine.getQueryBuilder(startV).createEdgeTraversal(EdgeType.TREE, startV, loader.introspectorFromName(connectedNodeType[i])); - } - return this.engine.getQueryBuilder(startV).union(builders); - } - - private String addDBAliasedSuffix(String propName) { - return propName + AAIProperties.DB_ALIAS_SUFFIX; - } - - protected String getPropNameWithAliasIfNeeded(String nodeType, String propName) throws AAIUnknownObjectException { - - String retPropName = propName; - if( loader.introspectorFromName(nodeType).getPropertyMetadata(propName, PropertyMetadata.DB_ALIAS).isPresent() ){ - return propName + AAIProperties.DB_ALIAS_SUFFIX; - } - return retPropName; - } - -} + + targetNodeType + "] propertyName = [" + srcProp + "], propVal = [" + + valFromInstance + "] so related-lookup is being abandoned."); + return retHash; + } else { + Vertex tmpVtx = result.get(); + // Pick up the properties from the target vertex that they wanted us to get + for (int j = 0; j < propCollectList.size(); j++) { + String tmpPropName = propCollectList.get(j); + tmpPropName = getPropNameWithAliasIfNeeded(targetNodeType, tmpPropName); + Object valObj = tmpVtx.<Object>property(tmpPropName).orElse(null); + String lookupKey = targetNodeType + "." + tmpPropName; + retHash.put(lookupKey, valObj); + + } + } + } + + return retHash; + + } // End of getNamedQueryExtraDataLookup() + + /** + * Collect NQ element hash. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param thisLevelElemVtx the element verrtx for this level + * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this + * nq-element vertex) from the top + * @param currentHash the current hash + * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get + * to this point + * @param levelCounter the level counter + * @return HashMap of all widget-points on a namedQuery topology with the value being the + * "named-query-element-uuid" for that spot. + * @throws AAIException the AAI exception + */ + public Map<String, String> collectNQElementHash(String transId, String fromAppId, + Vertex thisLevelElemVtx, String incomingTrail, Map<String, String> currentHash, + List<String> vidsTraversed, int levelCounter) throws AAIException { + + levelCounter++; + + Map<String, String> thisHash = new HashMap<>(); + thisHash.putAll(currentHash); + + if (levelCounter > MAX_LEVELS) { + throw new AAIException("AAI_6125", + "collectNQElementHash() has looped across more levels than allowed: " + MAX_LEVELS + + ". "); + } + String thisGuysTrail = ""; + String thisElemVid = thisLevelElemVtx.id().toString(); + + // Find out what widget (and thereby what aai-node-type) this element represents. + String thisElementNodeType = + getNqElementWidgetType(transId, fromAppId, thisLevelElemVtx, incomingTrail); + + if (incomingTrail == null || incomingTrail.equals("")) { + // This is the first one + thisGuysTrail = thisElementNodeType; + } else { + thisGuysTrail = incomingTrail + "|" + thisElementNodeType; + } + vidsTraversed.add(thisElemVid); + + String nqElementUuid = + thisLevelElemVtx.<String>property("named-query-element-uuid").orElse(null); + if (nqElementUuid == null || nqElementUuid.equals("")) { + String msg = " named-query element UUID not found at trail = [" + incomingTrail + "]."; + throw new AAIException("AAI_6133", msg); + } + thisHash.put(thisGuysTrail, nqElementUuid); + + // Now go "down" and look at the sub-elements pointed to so we can get their data. + Iterator<Vertex> vertI = + this.traverseIncidentEdges(EdgeType.TREE, thisLevelElemVtx, "named-query-element"); + while (vertI != null && vertI.hasNext()) { + Vertex tmpVert = vertI.next(); + String vid = tmpVert.id().toString(); + Map<String, Object> elementHash = new HashMap(); + + String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if (connectToType != null && connectToType.equals("named-query-element")) { + // This is what we would expect + elementHash.put(vid, tmpVert); + } else { + String msg = " named query element has [connectedTo] edge to improper nodeType= [" + + connectToType + "] trail = [" + incomingTrail + "]."; + throw new AAIException("AAI_6133", msg); + } + for (Map.Entry<String, Object> entry : elementHash.entrySet()) { + Vertex elVert = (Vertex) (entry.getValue()); + String tmpElVid = elVert.id().toString(); + if (!vidsTraversed.contains(tmpElVid)) { + // This is one we would like to use - so we'll recursively get it's result set + // to add to ours + Map<String, String> tmpHash = collectNQElementHash(transId, fromAppId, elVert, + thisGuysTrail, currentHash, vidsTraversed, levelCounter); + thisHash.putAll(tmpHash); + } + } + } + return thisHash; + + } // End of collectNQElementHash() + + /** + * Collect delete key hash. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param thisLevelElemVtx the element vertex at this level + * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this vertex) + * from the top + * @param currentHash the current hash + * @param vidsTraversed the vids traversed ---- ArrayList of vertexId's that we traversed to get + * to this point + * @param levelCounter the level counter + * @param modConstraintHash the mod constraint hash + * @param overRideModelId the over ride model id + * @param overRideModelVersionId the over ride model version id + * @return HashMap of all widget-points on a model topology with the value being the + * "newDataDelFlag" for that spot. + * @throws AAIException the AAI exception + */ + public Map<String, String> collectDeleteKeyHash(String transId, String fromAppId, + Vertex thisLevelElemVtx, String incomingTrail, Map<String, String> currentHash, + List<String> vidsTraversed, int levelCounter, Map<String, Vertex> modConstraintHash, + String overRideModelId, String overRideModelVersionId) throws AAIException { + + levelCounter++; + + Map<String, String> thisHash = new HashMap<>(); + thisHash.putAll(currentHash); + + if (levelCounter > MAX_LEVELS) { + throw new AAIException("AAI_6125", + "collectDeleteKeyHash() has looped across more levels than allowed: " + MAX_LEVELS + + ". "); + } + String thisGuysTrail = ""; + String thisElemVid = thisLevelElemVtx.id().toString(); + Map<String, Vertex> modConstraintHash2Use = null; + + // If this element represents a resource or service model, then we will replace this element + // with + // the "top" element of that resource or service model. That model-element already points to + // its + // topology, so it will graft in that model's topology. + // EXCEPT - if this element has "linkage-points" defined, then we need to do some extra + // processing for how we join to that model and will not try to go any "deeper". + List<String> linkagePtList = new ArrayList<>(); + Iterator<VertexProperty<Object>> vpI = thisLevelElemVtx.properties("linkage-points"); + + // I am not sure why, but since "linkage-points" is an xml-element-wrapper in the OXM + // definition, + // we get back the whole array of Strings in one String - but still use the + // "vtx.properties()" to + // get it - but only look at the first thing returned by the iterator. + if (vpI.hasNext()) { + String tmpLinkageThing = (String) vpI.next().value(); + linkagePtList = makeSureItsAnArrayList(tmpLinkageThing); + } + + if (linkagePtList != null && !linkagePtList.isEmpty()) { + // Whatever this element is - we are connecting to it via a linkage-point + // We will figure out what to do and then return without going any deeper + String elemFlag = thisLevelElemVtx.<String>property("new-data-del-flag").orElse(null); + + Set<String> linkageConnectNodeTypes = getLinkageConnectNodeTypes(linkagePtList); + Iterator<?> linkNtIter = linkageConnectNodeTypes.iterator(); + String incTrail = ""; + if (incomingTrail != null && !incomingTrail.equals("")) { + incTrail = incomingTrail + "|"; + } + + while (linkNtIter.hasNext()) { + // The 'trail' (or trails) for this element should just be the to the first-contact + // on the linkage point + String linkTrail = incTrail + linkNtIter.next(); + Boolean alreadyTaggedFalse = false; + if (thisHash.containsKey(linkTrail) && thisHash.get(linkTrail).equals("F")) { + // some other path with a matching trail has the deleteFlag set to "F", so we do + // not want + // to override that since our model code only uses nodeTypes to know where it is + // - and we + // would rather do less deleting than needed instead of too much deleting. + alreadyTaggedFalse = true; + } + if (elemFlag != null && elemFlag.equals("T") && !alreadyTaggedFalse) { + // This trail should be marked with an "T" + thisHash.put(linkTrail, "T"); + } else { + thisHash.put(linkTrail, "F"); + } + } + return thisHash; + } + + // ---------------------------------------------------------------------------- + // If we got to here, then this was not an element that used a linkage-point + // ---------------------------------------------------------------------------- + + // Find out what widget-model (and thereby what aai-node-type) this element represents. + // Even if this element is pointing to a service or resource model, it must have a + // first element which is a single widget-type model. + String thisElementNodeType = getModElementWidgetType(thisLevelElemVtx, incomingTrail); + String firstElementModelInfo = ""; + + vidsTraversed.add(thisElemVid); + Vertex elementVtxForThisLevel = null; + Vertex thisElementsModelVerVtx = + getModelVerThatElementRepresents(thisLevelElemVtx, incomingTrail); + Vertex thisElementsModelVtx = getModelGivenModelVer(thisElementsModelVerVtx, incomingTrail); + String modType = getModelTypeFromModel(thisElementsModelVtx, incomingTrail); + String subModelFirstModInvId = + thisElementsModelVtx.<String>property("model-invariant-id").orElse(null); + String subModelFirstVerId = + thisElementsModelVerVtx.<String>property("model-version-id").orElse(null); + if (modType.equals("widget")) { + if (overRideModelId != null && !overRideModelId.equals("")) { + // Note - this is just to catch the correct model for the TOP node in a model since + // it will have an element which will always be a widget even though the model + // could be a resource or service model. + firstElementModelInfo = "," + overRideModelId + "," + overRideModelVersionId; + } + } else if (nodeTypeSupportsPersona(thisElementNodeType)) { + firstElementModelInfo = "," + subModelFirstModInvId + "," + subModelFirstVerId; + } + + if (incomingTrail.equals("")) { + // This is the first one + thisGuysTrail = thisElementNodeType + firstElementModelInfo; + } else { + thisGuysTrail = incomingTrail + "|" + thisElementNodeType + firstElementModelInfo; + } + + String tmpFlag = "F"; + Boolean stoppedByASvcOrResourceModelElement = false; + if (modType.equals("widget")) { + elementVtxForThisLevel = thisLevelElemVtx; + // For the element-model for the widget at this level, record it's delete flag + tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null); + } else { + // For an element that is referring to a resource or service model, we replace + // this element with the "top" element for that resource/service model so that the + // topology of that resource/service model will be included in this topology. + String modelVerId = + thisElementsModelVerVtx.<String>property("model-version-id").orElse(null); + if (subModelFirstModInvId == null || subModelFirstModInvId.equals("") + || subModelFirstVerId == null || subModelFirstVerId.equals("")) { + throw new AAIException("AAI_6132", + "Bad Model Definition: Bad model-invariant-id or model-version-id. Model-version-id = " + + modelVerId + ", at [" + incomingTrail + "]"); + } + + // BUT -- if the model-element HERE at the resource/service level does NOT have + // it's new-data-del-flag set to "T", then we do not need to go down into the + // sub-model looking for delete-able things. + + tmpFlag = thisLevelElemVtx.<String>property("new-data-del-flag").orElse(null); + elementVtxForThisLevel = + getTopElementForSvcOrResModelVer(thisElementsModelVerVtx, thisGuysTrail); + if (tmpFlag != null && tmpFlag.equals("T")) { + modConstraintHash2Use = getModConstraintHash(thisLevelElemVtx, modConstraintHash); + } else { + stoppedByASvcOrResourceModelElement = true; + } + // For the element-model for the widget at this level, record it's delete flag + tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null); + } + + String flag2Use = "F"; // by default we'll use "F" for the delete flag + if (!stoppedByASvcOrResourceModelElement) { + // Since we haven't been stopped by a resource/service level "F", we can look at the + // lower level flag + if (thisHash.containsKey(thisGuysTrail)) { + // We've seen this spot in the topology before - do not override the delete flag if + // the older one is "F" + // We will only over-ride it if the old one was "T" and the new one is "F" (anything + // but "T") + String oldFlag = thisHash.get(thisGuysTrail); + if (oldFlag.equals("T") && (tmpFlag != null) && tmpFlag.equals("T")) { + // The old flag was "T" and the new flag is also "T" + flag2Use = "T"; + } else { + // the old flag was not "F" - so don't override it + flag2Use = "F"; + } + } else if ((tmpFlag != null) && tmpFlag.equals("T")) { + // We have not seen this one, so we can set it to "T" if that's what it is. + flag2Use = "T"; + } + } + + thisHash.put(thisGuysTrail, flag2Use); + if (!stoppedByASvcOrResourceModelElement) { + // Since we haven't been stopped by a resource/service level "F", we will continue to + // go "down" and look at the elements pointed to so we can get their data. + Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, + elementVtxForThisLevel, "model-element", "constrained-element-set"); + while (vertI != null && vertI.hasNext()) { + Vertex tmpVert = vertI.next(); + String vid = tmpVert.id().toString(); + Map<String, Object> elementHash = new HashMap<>(); + + String connectToType = + tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if (connectToType != null && connectToType.equals("model-element")) { + // A nice, regular old model-element + elementHash.put(vid, tmpVert); + } else if ((connectToType != null) + && connectToType.equals("constrained-element-set")) { + // translate the constrained-element-set into a hash of model-element Vertex's + String constrainedElementSetUuid = + tmpVert.<String>property("constrained-element-set-uuid").orElse(null); + if ((modConstraintHash2Use != null) + && modConstraintHash2Use.containsKey(constrainedElementSetUuid)) { + // This constrained-element-set is being superseded by a different one + Vertex replacementConstraintVert = + modConstraintHash.get(constrainedElementSetUuid); + elementHash = getNextStepElementsFromSet(replacementConstraintVert); + // Now that we've found and used the replacement constraint, we don't need + // to carry it along any farther + modConstraintHash.remove(constrainedElementSetUuid); + } else { + elementHash = getNextStepElementsFromSet(tmpVert); + } + } else { + String msg = " model-element has [connectedTo] edge to improper nodeType= [" + + connectToType + "] trail = [" + incomingTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + for (Map.Entry<String, Object> entry : elementHash.entrySet()) { + Vertex elVert = (Vertex) (entry.getValue()); + String tmpElVid = elVert.id().toString(); + String tmpElNT = getModElementWidgetType(elVert, thisGuysTrail); + check4EdgeRule(tmpElNT, thisElementNodeType); + if (!vidsTraversed.contains(tmpElVid)) { + // This is one we would like to use - so we'll recursively get it's result + // set to add to ours + Map<String, String> tmpHash = collectDeleteKeyHash(transId, fromAppId, + elVert, thisGuysTrail, currentHash, vidsTraversed, levelCounter, + modConstraintHash2Use, "", ""); + thisHash.putAll(tmpHash); + } + } + } + } + return thisHash; + + } // End of collectDeleteKeyHash() + + /** + * Gets the linkage connect node types. + * + * @param linkagePtList the linkage pt list + * @return the linkage connect node types + * @throws AAIException the AAI exception + */ + public Set<String> getLinkageConnectNodeTypes(List<String> linkagePtList) throws AAIException { + // linkage points are a path from the top of a model to where we link in. + // This method wants to just bring back a list of distinct last items. + // Ie: for the input with these two: "pserver|lag-link|l-interface" and + // "pserver|p-interface|l-interface" + // it would just return a single item, "l-interface" since both linkage points end in that + // same node-type. + + Set<String> linkPtSet = new HashSet<>(); + + if (linkagePtList == null) { + String detail = " Bad (null) linkagePtList passed to getLinkageConnectNodeTypes() "; + throw new AAIException("AAI_6125", detail); + } + + for (int i = 0; i < linkagePtList.size(); i++) { + String[] trailSteps = linkagePtList.get(i).split("\\|"); + if (trailSteps == null || trailSteps.length == 0) { + String detail = " Bad incomingTrail passed to getLinkageConnectNodeTypes(): [" + + linkagePtList + "] "; + throw new AAIException("AAI_6125", detail); + } + String lastStepNT = trailSteps[trailSteps.length - 1]; + linkPtSet.add(lastStepNT); + } + + return linkPtSet; + + }// End getLinkageConnectNodeTypes() + + /** + * Collect topology for model-ver. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param thisLevelElemVtx vertex to collect for + * @param incomingTrail the incoming trail -- trail of nodeTypes/personaInfo that got us here + * (this vertex) from the top + * @param currentMap the current map -- map that got us to this point (that we will use as the + * base of the map we will return) + * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get + * to this point + * @param levelCounter the level counter + * @param modConstraintHash the mod constraint hash + * @param overRideModelInvId the override model-invariant-id + * @param overRideModelVersionId the override model-version-id + * @return Map of the topology + * @throws AAIException the AAI exception + */ + public Multimap<String, String> collectTopology4ModelVer(String transId, String fromAppId, + Vertex thisLevelElemVtx, String incomingTrail, Multimap<String, String> currentMap, + List<String> vidsTraversed, int levelCounter, Map<String, Vertex> modConstraintHash, + String overRideModelInvId, String overRideModelVersionId) throws AAIException { + + levelCounter++; + + Multimap<String, String> thisMap = ArrayListMultimap.create(); + thisMap.putAll(currentMap); + + if (levelCounter > MAX_LEVELS) { + throw new AAIException("AAI_6125", + "collectTopology4ModelVer() has looped across more levels than allowed: " + + MAX_LEVELS + ". "); + } + String thisGuysTrail = ""; + String thisElemVid = thisLevelElemVtx.id().toString(); + Map<String, Vertex> modConstraintHash2Use = null; + + // If this element represents a resource or service model, then we will replace this element + // with + // the "top" element of that resource or service model. That model-element already points to + // its + // topology, so it will graft in that model's topology. + // EXCEPT - if this element defines "linkage-points" defined, then we need to do some extra + // processing for how we join to that model. + + // Find out what widget-model (and thereby what aai-node-type) this element represents. + // Even if this element is pointing to a service or resource model, it must have a + // first element which is a single widget-type model. + String firstElementModelInfo = ""; + String thisElementNodeType = getModElementWidgetType(thisLevelElemVtx, incomingTrail); + if (nodeTypeSupportsPersona(thisElementNodeType) && overRideModelInvId != null + && !overRideModelInvId.equals("")) { + firstElementModelInfo = "," + overRideModelInvId + "," + overRideModelVersionId; + } + + Vertex elementVtxForThisLevel = null; + Vertex thisElementsModelVerVtx = + getModelVerThatElementRepresents(thisLevelElemVtx, incomingTrail); + String subModelFirstModInvId = ""; + String subModelFirstModVerId = ""; + String modInfo4Trail = ""; + String modType = getModelTypeFromModelVer(thisElementsModelVerVtx, incomingTrail); + if (modType.equals("resource") || modType.equals("service")) { + // For an element that is referring to a resource or service model, we replace this + // this element with the "top" element for that resource/service model so that the + // topology of that resource/service model gets included in this topology. + // -- Note - since that top element of a service or resource model will point to a + // widget model, + // we have to track what modelId/version it really maps so we can make our recursive + // call + Vertex thisElementsModelVtx = + getModelGivenModelVer(thisElementsModelVerVtx, incomingTrail); + subModelFirstModInvId = + thisElementsModelVtx.<String>property("model-invariant-id").orElse(null); + subModelFirstModVerId = + thisElementsModelVerVtx.<String>property("model-version-id").orElse(null); + + if (nodeTypeSupportsPersona(thisElementNodeType)) { + modInfo4Trail = "," + subModelFirstModInvId + "," + subModelFirstModVerId; + } + String modelVerId = + thisElementsModelVerVtx.<String>property("model-version-id").orElse(null); + if (subModelFirstModInvId == null || subModelFirstModInvId.equals("") + || subModelFirstModVerId == null || subModelFirstModVerId.equals("")) { + throw new AAIException("AAI_6132", + "Bad Model Definition: Bad model-invariant-id or model-version-id. Model-ver-id = " + + modelVerId); + } + + elementVtxForThisLevel = + getTopElementForSvcOrResModelVer(thisElementsModelVerVtx, incomingTrail); + modConstraintHash2Use = getModConstraintHash(thisLevelElemVtx, modConstraintHash); + } else { + elementVtxForThisLevel = thisLevelElemVtx; + } + + if (incomingTrail.equals("")) { + // This is the first one + thisGuysTrail = thisElementNodeType + firstElementModelInfo; + } else { + thisGuysTrail = incomingTrail + "|" + thisElementNodeType + modInfo4Trail; + } + + // We only want to ensure that a particular element does not repeat on a single "branch". + // It could show up on other branches in the case where it is a sub-model which is being + // used in more than one place. + // + List<String> thisTrailsVidsTraversed = new ArrayList<>(vidsTraversed); + thisTrailsVidsTraversed.add(thisElemVid); + + // Look at the elements pointed to at this level and add on their data + Iterator<Vertex> vertI = this.traverseIncidentEdges(EdgeType.TREE, elementVtxForThisLevel, + "model-element", "constrained-element-set"); + + while (vertI != null && vertI.hasNext()) { + Vertex tmpVert = vertI.next(); + String vid = tmpVert.id().toString(); + Map<String, Object> elementHash = new HashMap<>(); + String connectToType = tmpVert.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if (connectToType != null && connectToType.equals("model-element")) { + // A nice, regular old model-element + elementHash.put(vid, tmpVert); + } else if ((connectToType != null) && connectToType.equals("constrained-element-set")) { + // translate the constrained-element-set into a hash of model-element Vertex's + String constrainedElementSetUuid = + tmpVert.<String>property("constrained-element-set-uuid").orElse(null); + if ((modConstraintHash2Use != null) + && modConstraintHash2Use.containsKey(constrainedElementSetUuid)) { + // This constrained-element-set is being superseded by a different one + Vertex replacementConstraintVert = + modConstraintHash.get(constrainedElementSetUuid); + elementHash = getNextStepElementsFromSet(replacementConstraintVert); + // Now that we've found and used the replacement constraint, we don't need to + // carry it along any farther + modConstraintHash.remove(constrainedElementSetUuid); + } else { + elementHash = getNextStepElementsFromSet(tmpVert); + } + } else { + String msg = " model element has [connectedTo] edge to improper nodeType= [" + + connectToType + "] trail = [" + incomingTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + for (Map.Entry<String, Object> entry : elementHash.entrySet()) { + Vertex elVert = (Vertex) (entry.getValue()); + String tmpElVid = elVert.id().toString(); + String tmpElNT = getModElementWidgetType(elVert, thisGuysTrail); + String tmpElStepName = getModelElementStepName(elVert, thisGuysTrail); + + List<String> linkagePtList = new ArrayList<>(); + Iterator<VertexProperty<Object>> vpI = elVert.properties("linkage-points"); + + // I am not sure why, but since "linkage-points" is an xml-element-wrapper in the + // OXM definition, + // we get back the whole array of Strings in one String - but still use the + // "vtx.properties()" to + // get it - but only look at the first thing returned by the iterator. + if (vpI.hasNext()) { + String tmpLinkageThing = (String) vpI.next().value(); + linkagePtList = makeSureItsAnArrayList(tmpLinkageThing); + } + + if (linkagePtList != null && !linkagePtList.isEmpty()) { + // This is as far as we can go, we will use the linkage point info to define the + // rest of this "trail" + for (int i = 0; i < linkagePtList.size(); i++) { + Multimap<String, String> tmpMap = collectTopology4LinkagePoint(transId, + fromAppId, linkagePtList.get(i), thisGuysTrail, currentMap); + thisMap.putAll(tmpMap); + } + } else { + check4EdgeRule(tmpElNT, thisElementNodeType); + thisMap.put(thisGuysTrail, tmpElStepName); + if (!thisTrailsVidsTraversed.contains(tmpElVid)) { + // This is one we would like to use - so we'll recursively get it's result + // set to add to ours + Multimap<String, String> tmpMap = collectTopology4ModelVer(transId, + fromAppId, elVert, thisGuysTrail, currentMap, thisTrailsVidsTraversed, + levelCounter, modConstraintHash2Use, subModelFirstModInvId, + subModelFirstModVerId); + thisMap.putAll(tmpMap); + } else { + String modelElementUuid = + elVert.<String>property("model-element-uuid").orElse(null); + String msg = + "Bad Model Definition: looping model-element (model-element-uuid = [" + + modelElementUuid + "]) found trying to add step: [" + + tmpElStepName + "], " + " on trail = [" + thisGuysTrail + "]. "; + System.out.println(msg); + throw new AAIException("AAI_6132", msg); + } + } + } + } + + return thisMap; + + } // End of collectTopology4ModelVer() + + /** + * Check 4 edge rule. + * + * @param nodeTypeA the node type A + * @param nodeTypeB the node type B + * @throws AAIException the AAI exception + */ + public void check4EdgeRule(String nodeTypeA, String nodeTypeB) throws AAIException { + // Throw an exception if there is no defined edge rule for this combination of nodeTypes in + // DbEdgeRules. + + final EdgeIngestor edgeRules = + SpringContextAware.getApplicationContext().getBean(EdgeIngestor.class); + // final EdgeRules edgeRules = EdgeRules.getInstance(); + + EdgeRuleQuery.Builder baseQ = new EdgeRuleQuery.Builder(nodeTypeA, nodeTypeB); + if (!edgeRules.hasRule(baseQ.build())) { + + /* + * if( !edgeRules.hasEdgeRule(nodeTypeA, nodeTypeB) + * && !edgeRules.hasEdgeRule(nodeTypeB, nodeTypeA) ){ + */ + // There's no EdgeRule for this -- find out if one of the nodeTypes is invalid or if + // they are valid, but there's just no edgeRule for them. + try { + loader.introspectorFromName(nodeTypeA); + } catch (AAIUnknownObjectException e) { + String emsg = " Unrecognized nodeType aa [" + nodeTypeA + "]\n"; + throw new AAIException("AAI_6115", emsg); + } + try { + loader.introspectorFromName(nodeTypeB); + } catch (AAIUnknownObjectException e) { + String emsg = " Unrecognized nodeType bb [" + nodeTypeB + "]\n"; + throw new AAIException("AAI_6115", emsg); + } + + String msg = " No Edge Rule found for this pair of nodeTypes (order does not matter) [" + + nodeTypeA + "], [" + nodeTypeB + "]."; + throw new AAIException("AAI_6120", msg); + } + + } + + /** + * Collect topology 4 linkage point. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param linkagePointStrVal -- Note it is in reverse order from where we connect to it. + * @param incomingTrail -- trail of nodeTypes that got us here (this vertex) from the top + * @param currentMap the current map -- that got us to this point (that we will use as the base + * of the map we will return) + * @return Map of the topology + * @throws AAIException the AAI exception + */ + public Multimap<String, String> collectTopology4LinkagePoint(String transId, String fromAppId, + String linkagePointStrVal, String incomingTrail, Multimap<String, String> currentMap) + throws AAIException { + + Multimap<String, String> thisMap = ArrayListMultimap.create(); + thisMap.putAll(currentMap); + String thisGuysTrail = incomingTrail; + + // NOTE - "trails" can have multiple parts now since we track persona info for some. + // We just want to look at the node type info - which would be the piece + // before any commas (if there are any). + + String[] trailSteps = thisGuysTrail.split("\\|"); + if (trailSteps.length == 0) { + throw new AAIException("AAI_6125", + "Bad incomingTrail passed to collectTopology4LinkagePoint(): [" + incomingTrail + + "] "); + } + String lastStepString = trailSteps[trailSteps.length - 1]; + String[] stepPieces = lastStepString.split(","); + String lastStepNT = stepPieces[0]; + + // It is assumed that the linkagePoint string will be a pipe-delimited string where each + // piece is an AAIProperties.NODE_TYPE. For now, the first thing to connect to is what is on + // the farthest right. + // Example: linkagePoint = "pserver|p-interface|l-interface" would mean that we're + // connecting to the l-interface + // but that after that, we connect to a p-interface followed by a pserver. + // It might have been more clear to define it in the other direction, but for now, that is + // it. (16-07) + String linkagePointStr = linkagePointStrVal; + + // We are getting these with more than linkage thing in one string. + // Ie. "pserver|lag-interface|l-interface, pserver|p-interface|l-interface, + // vlan|l-interface" + linkagePointStr = linkagePointStr.replace("[", ""); + linkagePointStr = linkagePointStr.replace("]", ""); + linkagePointStr = linkagePointStr.replace(" ", ""); + + String[] linkage = linkagePointStr.split("\\,"); + for (int x = 0; x < linkage.length; x++) { + lastStepNT = stepPieces[0]; + String thisStepNT = ""; + String[] linkageSteps = linkage[x].split("\\|"); + if (linkageSteps.length == 0) { + throw new AAIException("AAI_6125", + "Bad linkagePointStr passed to collectTopology4LinkagePoint(): [" + + linkagePointStr + "] "); + } + for (int i = (linkageSteps.length - 1); i >= 0; i--) { + thisStepNT = linkageSteps[i]; + check4EdgeRule(lastStepNT, thisStepNT); + thisMap.put(thisGuysTrail, thisStepNT); + thisGuysTrail = thisGuysTrail + "|" + thisStepNT; + lastStepNT = thisStepNT; + } + } + return thisMap; + + } // End of collectTopology4LinkagePoint() + + /** + * Gets the next step elements from set. + * + * @param constrElemSetVtx the constr elem set vtx + * @return Hash of the set of model-elements this set represents + * @throws AAIException the AAI exception + */ + public Map<String, Object> getNextStepElementsFromSet(Vertex constrElemSetVtx) + throws AAIException { + // Take a constrained-element-set and figure out the total set of all the possible elements + // that it + // represents and return them as a Hash. + + Map<String, Object> retElementHash = new HashMap<>(); + + if (constrElemSetVtx == null) { + String msg = " getNextStepElementsFromSet() called with null constrElemSetVtx "; + throw new AAIException("AAI_6125", msg); + } + + String constrNodeType = + constrElemSetVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); + String constrElemSetUuid = + constrElemSetVtx.<String>property("constrained-element-set-uuid").orElse(null); + if (constrNodeType == null || !constrNodeType.equals("constrained-element-set")) { + String msg = " getNextStepElementsFromSet() called with wrong type model: [" + + constrNodeType + "]. "; + throw new AAIException("AAI_6125", msg); + } + + ArrayList<Vertex> choiceSetVertArray = new ArrayList<>(); + Iterator<Vertex> vertI = + this.traverseIncidentEdges(EdgeType.TREE, constrElemSetVtx, "element-choice-set"); + int setCount = 0; + while (vertI != null && vertI.hasNext()) { + Vertex choiceSetVertex = vertI.next(); + String constrSetType = + choiceSetVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if (constrSetType != null && constrSetType.equals("element-choice-set")) { + choiceSetVertArray.add(choiceSetVertex); + setCount++; + } + } + + if (setCount == 0) { + String msg = "No element-choice-set found under constrained-element-set-uuid = " + + constrElemSetUuid; + throw new AAIException("AAI_6132", msg); + } + + // Loop through each choice-set and grab the model-elements + for (int i = 0; i < setCount; i++) { + Vertex choiceSetVert = choiceSetVertArray.get(i); + Iterator<Vertex> mVertI = + this.traverseIncidentEdges(EdgeType.TREE, choiceSetVert, "model-element"); + int elCount = 0; + while (mVertI != null && mVertI.hasNext()) { + Vertex tmpElVertex = mVertI.next(); + String elNodeType = + tmpElVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if (elNodeType != null && elNodeType.equals("model-element")) { + String tmpVid = tmpElVertex.id().toString(); + retElementHash.put(tmpVid, tmpElVertex); + elCount++; + } else { + // unsupported node type found for this choice-set + String msg = "Unsupported nodeType (" + elNodeType + + ") found under choice-set under constrained-element-set-uuid = " + + constrElemSetUuid; + throw new AAIException("AAI_6132", msg); + } + } + + if (elCount == 0) { + String msg = + "No model-elements found in choice-set under constrained-element-set-uuid = " + + constrElemSetUuid; + throw new AAIException("AAI_6132", msg); + } + + } + return retElementHash; + + } // End of getNextStepElementsFromSet() + + /** + * Gen topo map 4 named Q. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param queryVertex the query vertex + * @param namedQueryUuid the named query uuid + * @return MultiMap of valid next steps for each potential query-element + * @throws AAIException the AAI exception + */ + public Multimap<String, String> genTopoMap4NamedQ(String transId, String fromAppId, + Vertex queryVertex, String namedQueryUuid) throws AAIException { + + if (queryVertex == null) { + throw new AAIException("AAI_6125", "null queryVertex passed to genTopoMap4NamedQ()"); + } + + Multimap<String, String> initialEmptyMap = ArrayListMultimap.create(); + List<String> vidsTraversed = new ArrayList<>(); + + Vertex firstElementVertex = null; + Iterator<Vertex> vertI = + this.traverseIncidentEdges(EdgeType.TREE, queryVertex, "named-query-element"); + int elCount = 0; + while (vertI != null && vertI.hasNext()) { + elCount++; + firstElementVertex = vertI.next(); + } + + if (elCount > 1) { + throw new AAIException("AAI_6133", + "Illegal query defined: More than one first element defined for = " + + namedQueryUuid); + } + + if (firstElementVertex == null) { + throw new AAIException("AAI_6114", + "Could not find first query element = " + namedQueryUuid); + } + + Vertex modVtx = getModelThatNqElementRepresents(firstElementVertex, ""); + String modelType = getModelTypeFromModel(modVtx, ""); + if (!modelType.equals("widget")) { + throw new AAIException("AAI_6133", + "Bad Named Query Definition: First element must correspond to a widget type model. Named Query UUID = " + + namedQueryUuid); + } + + return collectTopology4NamedQ(transId, fromAppId, firstElementVertex, "", initialEmptyMap, + vidsTraversed, 0); + } // End of genTopoMap4NamedQ() + + /** + * Collect topology 4 named Q. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param thisLevelElemVtx the model element vertex for this level + * @param levelCounter the level counter + * @return resultSet + * @throws AAIException the AAI exception + */ + public Multimap<String, String> collectTopology4NamedQ(String transId, String fromAppId, + Vertex thisLevelElemVtx, String incomingTrail, Multimap<String, String> currentMap, + List<String> vidsTraversed, int levelCounter) throws AAIException { + + levelCounter++; + + Multimap<String, String> thisMap = ArrayListMultimap.create(); + thisMap.putAll(currentMap); + + String thisElemVid = thisLevelElemVtx.id().toString(); + if (levelCounter > MAX_LEVELS) { + throw new AAIException("AAI_6125", + "collectModelStructure() has looped across more levels than allowed: " + MAX_LEVELS + + ". "); + } + String thisGuysTrail = ""; + + // find out what widget (and thereby what aai-node-type) this element represents + String thisElementNodeType = + getNqElementWidgetType(transId, fromAppId, thisLevelElemVtx, incomingTrail); + + if (incomingTrail.equals("")) { + // This is the first one + thisGuysTrail = thisElementNodeType; + } else { + thisGuysTrail = incomingTrail + "|" + thisElementNodeType; + } + + vidsTraversed.add(thisElemVid); + // Look at the elements pointed to at this level and add on their data + Iterator<Vertex> vertI = + this.traverseIncidentEdges(EdgeType.TREE, thisLevelElemVtx, "named-query-element"); + while (vertI != null && vertI.hasNext()) { + Vertex tmpVert = vertI.next(); + String tmpVid = tmpVert.id().toString(); + String tmpElNT = getNqElementWidgetType(transId, fromAppId, tmpVert, thisGuysTrail); + thisMap.put(thisGuysTrail, tmpElNT); + if (!vidsTraversed.contains(tmpVid)) { + // This is one we would like to use - so we'll recursively get it's result set to + // add to ours + Multimap<String, String> tmpMap = collectTopology4NamedQ(transId, fromAppId, + tmpVert, thisGuysTrail, currentMap, vidsTraversed, levelCounter); + thisMap.putAll(tmpMap); + } + } + + return thisMap; + + } // End of collectTopology4NamedQ() + + /** + * Gets the model that NamedQuery element represents. + * + * @param elementVtx the NQ element vtx + * @param elementTrail the element trail + * @return the model that element represents + * @throws AAIException the AAI exception + */ + public Vertex getModelThatNqElementRepresents(Vertex elementVtx, String elementTrail) + throws AAIException { + + // Get the model that a named-query element represents + Vertex modVtx = null; + Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.COUSIN, elementVtx, "model"); + int modCount = 0; + while (mvertI != null && mvertI.hasNext()) { + modCount++; + modVtx = mvertI.next(); + } + + if (modCount > 1) { + String msg = + "Illegal element defined: More than one model pointed to by a single named-query-element at [" + + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + if (modVtx == null) { + String msg = "Bad named-query definition: Could not find model for element. "; + if (!elementTrail.equals("")) { + msg = + "Bad named-query definition: Could not find model for named-query-element at [" + + elementTrail + "]."; + } + throw new AAIException("AAI_6132", msg); + } + + String nodeType = modVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if ((nodeType != null) && nodeType.equals("model")) { + return modVtx; + } else { + String msg = + "Illegal Named Query element defined: expecting a 'model', but found 'isA' edge pointing to nodeType = " + + nodeType + "] at [" + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + }// getModelThatNqElementRepresents() + + /** + * Gets the model-ver that element represents. + * + * @param elementVtx the element vtx + * @param elementTrail the element trail + * @return the model-ver that element represents + * @throws AAIException the AAI exception + */ + public Vertex getModelVerThatElementRepresents(Vertex elementVtx, String elementTrail) + throws AAIException { + + // Get the model-ver that an element represents + Vertex modVerVtx = null; + Iterator<Vertex> mvertI = + this.traverseIncidentEdges(EdgeType.COUSIN, elementVtx, "model-ver"); + int modCount = 0; + while (mvertI != null && mvertI.hasNext()) { + modCount++; + modVerVtx = mvertI.next(); + } + + if (modCount > 1) { + String msg = + "Illegal element defined: More than one model pointed to by a single element at [" + + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + if (modVerVtx == null) { + String msg = "Bad model definition: Could not find model-ver for model-element. "; + if (!elementTrail.equals("")) { + msg = "Bad model definition: Could not find model-VER for model-element at [" + + elementTrail + "]."; + } + throw new AAIException("AAI_6132", msg); + } + + String nodeType = modVerVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if ((nodeType != null) && nodeType.equals("model-ver")) { + return modVerVtx; + } else { + String msg = + "Illegal model-element defined: expecting a 'model-ver', but found 'isA' edge pointing to nodeType = " + + nodeType + "] at [" + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + }// getModelVerThatElementRepresents() + + /** + * Gets the model that is parent to model-ver node. + * + * @param modVerVtx the model-ver vtx + * @param elementTrail the element trail + * @return the model that element represents + * @throws AAIException the AAI exception + */ + public Vertex getModelGivenModelVer(Vertex modVerVtx, String elementTrail) throws AAIException { + + // Get the parent model for this "model-ver" node + Vertex modVtx = null; + Iterator<Vertex> mvertI = this.traverseIncidentEdges(EdgeType.TREE, modVerVtx, "model"); + int modCount = 0; + while (mvertI != null && mvertI.hasNext()) { + modCount++; + modVtx = mvertI.next(); + } + + if (modCount > 1) { + String msg = + "Illegal model-ver node defined: More than one model points to it with a 'has' edge [" + + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + if (modVtx == null) { + String msg = "Bad model-ver node: Could not find parent model. "; + if (!elementTrail.equals("")) { + msg = "Bad model-ver node: Could not find parent model. [" + elementTrail + "]."; + } + throw new AAIException("AAI_6132", msg); + } + + String nodeType = modVtx.<String>property(AAIProperties.NODE_TYPE).orElse(null); + if ((nodeType != null) && nodeType.equals("model")) { + // Found what we were looking for. + return modVtx; + } else { + // Something is amiss + String msg = + " Could not find parent model node for model-ver node at [" + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + }// getModelGivenModelVer() + + /** + * Gets the model type. + * + * @param modelVtx the model vtx + * @param elementTrail the element trail + * @return the model type + * @throws AAIException the AAI exception + */ + public String getModelTypeFromModel(Vertex modelVtx, String elementTrail) throws AAIException { + + // Get the model-type from a model vertex + if (modelVtx == null) { + String msg = " null modelVtx passed to getModelTypeFromModel() "; + throw new AAIException("AAI_6114", msg); + } + + String modelType = modelVtx.<String>property("model-type").orElse(null); + if ((modelType == null) || modelType.equals("")) { + String msg = + "Could not find model-type for model encountered at [" + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + if (!modelType.equals("widget") && !modelType.equals("resource") + && !modelType.equals("service")) { + String msg = "Unrecognized model-type, [" + modelType + + "] for model pointed to by element at [" + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + return modelType; + + }// getModelTypeFromModel() + + /** + * Gets the model type given model-ver + * + * @param modelVerVtx the model-ver vtx + * @param elementTrail the element trail + * @return the model type + * @throws AAIException the AAI exception + */ + public String getModelTypeFromModelVer(Vertex modelVerVtx, String elementTrail) + throws AAIException { + + // Get the model-type given a model-ver vertex + if (modelVerVtx == null) { + String msg = " null modelVerVtx passed to getModelTypeFromModelVer() "; + throw new AAIException("AAI_6114", msg); + } + + Vertex modVtx = getModelGivenModelVer(modelVerVtx, elementTrail); + String modelType = modVtx.<String>property("model-type").orElse(null); + if ((modelType == null) || modelType.equals("")) { + String msg = + "Could not find model-type for model encountered at [" + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + if (!modelType.equals("widget") && !modelType.equals("resource") + && !modelType.equals("service")) { + String msg = "Unrecognized model-type, [" + modelType + + "] for model pointed to by element at [" + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + return modelType; + + }// getModelTypeFromModelVer() + + /** + * Gets the model-element step name. + * + * @param elementVtx the model-element vtx + * @param elementTrail the element trail + * @return the element step name + * @throws AAIException the AAI exception + */ + public String getModelElementStepName(Vertex elementVtx, String elementTrail) + throws AAIException { + + // Get the "step name" for a model-element + // Step names look like this for widget-models: AAIProperties.NODE_TYPE + // Step names look like this for resource/service models: + // "aai-node-type,model-invariant-id,model-version-id" + // NOTE -- if the element points to a resource or service model, then we'll return the + // widget-type of the first element (crown widget) for that model. + String thisElementNodeType = "?"; + Vertex modVerVtx = getModelVerThatElementRepresents(elementVtx, elementTrail); + String modelType = getModelTypeFromModelVer(modVerVtx, elementTrail); + + if (modelType == null) { + String msg = + " could not determine modelType in getModelElementStepName(). elementTrail = [" + + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + if (modelType.equals("widget")) { + // NOTE: for models that have model-type = "widget", their "model-name" maps directly to + // aai-node-type + thisElementNodeType = modVerVtx.<String>property("model-name").orElse(null); + if ((thisElementNodeType == null) || thisElementNodeType.equals("")) { + String msg = + "Could not find model-name for the widget model pointed to by element at [" + + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + return thisElementNodeType; + } else if (modelType.equals("resource") || modelType.equals("service")) { + Vertex modVtx = getModelGivenModelVer(modVerVtx, elementTrail); + String modInvId = modVtx.<String>property("model-invariant-id").orElse(null); + String modVerId = modVerVtx.<String>property("model-version-id").orElse(null); + Vertex relatedTopElementModelVtx = + getTopElementForSvcOrResModelVer(modVerVtx, elementTrail); + Vertex relatedModelVtx = + getModelVerThatElementRepresents(relatedTopElementModelVtx, elementTrail); + thisElementNodeType = relatedModelVtx.<String>property("model-name").orElse(null); + + if ((thisElementNodeType == null) || thisElementNodeType.equals("")) { + String msg = + "Could not find model-name for the widget model pointed to by element at [" + + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + String stepName = ""; + if (nodeTypeSupportsPersona(thisElementNodeType)) { + // This nodeType that this resource or service model refers to does support + // persona-related fields, so + // we will use model-invariant-id and model-version-id as part of the step name. + stepName = thisElementNodeType + "," + modInvId + "," + modVerId; + } else { + stepName = thisElementNodeType; + } + return stepName; + } else { + String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + }// getModelElementStepName() + + /** + * Node type supports persona. + * + * @param nodeType the node type + * @return the boolean + * @throws AAIException the AAI exception + */ + public Boolean nodeTypeSupportsPersona(String nodeType) throws AAIException { + + if (nodeType == null || nodeType.equals("")) { + return false; + } + Introspector introspector = null; + try { + introspector = loader.introspectorFromName(nodeType); + } catch (AAIUnknownObjectException e) { + String emsg = " Unrecognized nodeType [" + nodeType + "]\n"; + throw new AAIException("AAI_6115", emsg); + } + + Collection<String> props4ThisNT = introspector.getProperties(); + return props4ThisNT.contains(addDBAliasedSuffix("model-invariant-id")) + && props4ThisNT.contains(addDBAliasedSuffix("model-version-id")); + + }// nodeTypeSupportsPersona() + + /** + * Gets a Named Query element's widget type. + * + * @param elementVtx the named-query element vtx + * @param elementTrail the element trail + * @return the element widget type + * @throws AAIException the AAI exception + */ + public String getNqElementWidgetType(String transId, String fromAppId, Vertex elementVtx, + String elementTrail) throws AAIException { + + String thisNqElementWidgetType = ""; + // Get the associated node-type for the model pointed to by a named-query-element. + // NOTE -- if the element points to a resource or service model, then we'll return the + // widget-type of the first element (crown widget) for that model. + Vertex modVtx = getModelThatNqElementRepresents(elementVtx, elementTrail); + String modelType = getModelTypeFromModel(modVtx, elementTrail); + + if (modelType == null || !modelType.equals("widget")) { + String emsg = " Model Type must be 'widget' for NamedQuery elements. Found [" + + modelType + "] at [" + elementTrail + "]\n"; + throw new AAIException("AAI_6132", emsg); + } else { + // For a Widget model, the nodeType is just mapped to the model-element.model-name + List<Vertex> modVerVtxArr = getModVersUsingModel(transId, fromAppId, modVtx); + if (modVerVtxArr != null && !modVerVtxArr.isEmpty()) { + thisNqElementWidgetType = + (modVerVtxArr.get(0)).<String>property("model-name").orElse(null); + } + if (thisNqElementWidgetType == null || thisNqElementWidgetType.equals("")) { + String emsg = " Widget type could not be determined at [" + elementTrail + "]\n"; + throw new AAIException("AAI_6132", emsg); + } else { + return thisNqElementWidgetType; + } + } + + }// End getNqElementWidgetType() + + /** + * Gets a model-element's top widget type. + * + * @param elementVtx the model element vtx + * @param elementTrail the element trail + * @return the element widget type + * @throws AAIException the AAI exception + */ + public String getModElementWidgetType(Vertex elementVtx, String elementTrail) + throws AAIException { + + // Get the associated node-type for the model-ver pointed to by a model-element. + // NOTE -- if the element points to a resource or service model, then we'll return the + // widget-type of the first element (crown widget) for that model. + Vertex modVerVtx = getModelVerThatElementRepresents(elementVtx, elementTrail); + return getModelVerTopWidgetType(modVerVtx, elementTrail); + + }// End getModElementWidgetType() + + /** + * Gets the node using unique identifier + * + * @param transId the trans id + * @param fromAppId the from app id + * @param nodeType the nodeType + * @param idPropertyName the property name of the unique identifier + * @param uniqueIdVal the UUID value + * @return unique vertex found using UUID + * @throws AAIException the AAI exception + */ + public Vertex getNodeUsingUniqueId(String transId, String fromAppId, String nodeType, + String idPropertyName, String uniqueIdVal) throws AAIException { + + // Given a unique identifier, get the Vertex + if (uniqueIdVal == null || uniqueIdVal.equals("")) { + String emsg = + " Bad uniqueIdVal passed to getNodeUsingUniqueId(): [" + uniqueIdVal + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + if (idPropertyName == null || idPropertyName.equals("")) { + String emsg = + " Bad idPropertyName passed to getNodeUsingUniqueId(): [" + idPropertyName + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + if (nodeType == null || nodeType.equals("")) { + String emsg = " Bad nodeType passed to getNodeUsingUniqueId(): [" + nodeType + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + Vertex uniqVtx = null; + Iterable<?> uniqVerts = null; + uniqVerts = engine.asAdmin().getReadOnlyTraversalSource().V() + .has(AAIProperties.NODE_TYPE, nodeType).has(idPropertyName, uniqueIdVal).toList(); + if (uniqVerts == null) { + String emsg = + "Node could not be found for nodeType = [" + nodeType + "], propertyName = [" + + idPropertyName + "], propertyValue = [" + uniqueIdVal + "]\n"; + throw new AAIException("AAI_6114", emsg); + } else { + int count = 0; + Iterator<?> uniqVertsIter = uniqVerts.iterator(); + if (!uniqVertsIter.hasNext()) { + String emsg = + "Node could not be found for nodeType = [" + nodeType + "], propertyName = [" + + idPropertyName + "], propertyValue = [" + uniqueIdVal + "]\n"; + throw new AAIException("AAI_6114", emsg); + } else { + while (uniqVertsIter.hasNext()) { + count++; + uniqVtx = (Vertex) uniqVertsIter.next(); + if (count > 1) { + String emsg = "More than one node found for nodeType = [" + nodeType + + "], propertyName = [" + idPropertyName + "], propertyValue = [" + + uniqueIdVal + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + } + } + } + + return uniqVtx; + }// End getNodeUsingUniqueId() + + /** + * Gets the model-ver nodes using name. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelName the model name + * @return the model-ver's that use this name + * @throws AAIException the AAI exception + */ + public List<Vertex> getModelVersUsingName(String transId, String fromAppId, String modelName) + throws AAIException { + + // Given a "model-name", find the model-ver vertices that this maps to + if (modelName == null || modelName.equals("")) { + String emsg = " Bad modelName passed to getModelVersUsingName(): [" + modelName + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + List<Vertex> retVtxArr = new ArrayList<>(); + Iterator<Vertex> modVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V() + .has(AAIProperties.NODE_TYPE, "model-ver").has("model-name", modelName); + if (!modVertsIter.hasNext()) { + String emsg = + "Model-ver record(s) could not be found for model-ver data passed. model-name = [" + + modelName + "]\n"; + throw new AAIException("AAI_6132", emsg); + } else { + while (modVertsIter.hasNext()) { + Vertex tmpModelVerVtx = modVertsIter.next(); + retVtxArr.add(tmpModelVerVtx); + } + } + + return retVtxArr; + + }// End getModelVersUsingName() + + /** + * Gets the model-ver nodes using model-invariant-id. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelInvId-invariant-id (uniquely identifies a model) + * @return the model-ver's defined for the corresponding model + * @throws AAIException the AAI exception + */ + public Iterator<Vertex> getModVersUsingModelInvId(String transId, String fromAppId, + String modelInvId) throws AAIException { + + // Given a "model-invariant-id", find the model-ver nodes that this maps to + if (modelInvId == null || modelInvId.equals("")) { + String emsg = " Bad model-invariant-id passed to getModVersUsingModelInvId(): [" + + modelInvId + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + Vertex modVtx = + getNodeUsingUniqueId(transId, fromAppId, "model", "model-invariant-id", modelInvId); + List<Vertex> retVtxArr = getModVersUsingModel(transId, fromAppId, modVtx); + if (retVtxArr == null || retVtxArr.isEmpty()) { + String emsg = + " Model-ver record(s) could not be found attached to model with model-invariant-id = [" + + modelInvId + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + + return retVtxArr.iterator(); + }// End getModVersUsingModelInvId() + + /** + * Gets the model-ver nodes using a model node. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modVtx vertex + * @return the model-ver's defined for the corresponding model + * @throws AAIException the AAI exception + */ + public List<Vertex> getModVersUsingModel(String transId, String fromAppId, Vertex modVtx) + throws AAIException { + + if (modVtx == null) { + String emsg = " Null model vertex passed to getModVersUsingModel(): "; + throw new AAIException("AAI_6118", emsg); + } + + List<Vertex> retVtxArr = new ArrayList<>(); + Iterator<Vertex> modVerVertsIter = + this.traverseIncidentEdges(EdgeType.TREE, modVtx, "model-ver"); + if (!modVerVertsIter.hasNext()) { + String modelInvId = modVtx.<String>property("model-invariant-id").orElse(null); + String emsg = + "Model-ver record(s) could not be found attached to model with model-invariant-id = [" + + modelInvId + "]\n"; + throw new AAIException("AAI_6132", emsg); + } else { + while (modVerVertsIter.hasNext()) { + Vertex tmpModelVtx = modVerVertsIter.next(); + retVtxArr.add(tmpModelVtx); + } + } + + return retVtxArr; + + }// End getModVersUsingModel() + + /** + * Gets the model-version-ids using model-name. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelName the model name + * @return the model uuids using name + * @throws AAIException the AAI exception + */ + public List<String> getModelVerIdsUsingName(String transId, String fromAppId, String modelName) + throws AAIException { + + // Given a model-name find the model-ver nodes that it maps to + if (modelName == null || modelName.equals("")) { + String emsg = + " Bad modelName passed to getModelVerIdsUsingName(): [" + modelName + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + List<String> retArr = new ArrayList<>(); + Iterator<Vertex> modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V() + .has(AAIProperties.NODE_TYPE, "model-ver").has("model-name", modelName); + if (!modVerVertsIter.hasNext()) { + String emsg = + " model-ver record(s) could not be found for model data passed. model-name = [" + + modelName + "]\n"; + throw new AAIException("AAI_6114", emsg); + } else { + while (modVerVertsIter.hasNext()) { + Vertex modelVerVtx = modVerVertsIter.next(); + String tmpUuid = modelVerVtx.<String>property("model-version-id").orElse(null); + if ((tmpUuid != null) && !tmpUuid.equals("") && !retArr.contains(tmpUuid)) { + retArr.add(tmpUuid); + } + } + } + + if (retArr.isEmpty()) { + String emsg = "No model-ver record found for model-name = [" + modelName + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + + return retArr; + }// End getModelVerIdsUsingName() + + /** + * Gets the model top widget type. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVersionId the model-version-id + * @param modelInvId the model-invariant-id + * @param modelName the model-name + * @return the model top widget type + * @throws AAIException the AAI exception + */ + public String getModelVerTopWidgetType(String transId, String fromAppId, String modelVersionId, + String modelInvId, String modelName) throws AAIException { + + // Could be given a model-ver's key info (model-version-id), OR, just a (non-unique) + // model-name, + // Or just a model-invariant-id (which could have multiple model-ver records under it). + // In any case, they should only map to one single "top" node-type for the first element. + + String nodeType = "?"; + Iterator<Vertex> modVerVertsIter; + + if (modelVersionId != null && !modelVersionId.equals("")) { + // this would be the best - we can just look up the model-ver records directly + modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V() + .has(AAIProperties.NODE_TYPE, "model-ver").has("model-version-id", modelVersionId); + } else if (modelName != null && !modelName.equals("")) { + modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V() + .has(AAIProperties.NODE_TYPE, "model-ver").has("model-name", modelName); + } else if (modelInvId != null && !modelInvId.equals("")) { + modVerVertsIter = getModVersUsingModelInvId(transId, fromAppId, modelInvId); + } else { + String msg = + "Neither modelVersionId, modelInvariantId, nor modelName passed to: getModelVerTopWidgetType() "; + throw new AAIException("AAI_6120", msg); + } + + if (!modVerVertsIter.hasNext()) { + String emsg = + "model-ver record(s) could not be found for model data passed: modelInvariantId = [" + + modelInvId + "], modeVersionId = [" + modelVersionId + "], modelName = [" + + modelName + "]\n"; + throw new AAIException("AAI_6114", emsg); + } else { + String lastNT = ""; + if (!modVerVertsIter.hasNext()) { + String emsg = + "model-ver record(s) could not be found for model data passed: modelInvariantId = [" + + modelInvId + "], modeVersionId = [" + modelVersionId + "], modelName = [" + + modelName + "]\n"; + throw new AAIException("AAI_6114", emsg); + } + while (modVerVertsIter.hasNext()) { + Vertex tmpModVerVtx = modVerVertsIter.next(); + String tmpNT = getModelVerTopWidgetType(tmpModVerVtx, ""); + if (lastNT != null && !lastNT.equals("")) { + if (!lastNT.equals(tmpNT)) { + String emsg = "Different top-node-types (" + tmpNT + ", " + lastNT + + ") found for model data passed. (" + " modelVersionId = [" + + modelVersionId + "], modelId = [" + modelInvId + "], modelName = [" + + modelName + "])\n"; + throw new AAIException("AAI_6114", emsg); + } + } + lastNT = tmpNT; + nodeType = tmpNT; + } + } + + return nodeType; + + }// End getModelVerTopWidgetType() + + /** + * Gets the widget type that this model-ver starts with. + * + * @param modVerVtx the model-version vtx + * @param elementTrail the element trail + * @return the widget type of the starting node of this model + * @throws AAIException the AAI exception + */ + public String getModelVerTopWidgetType(Vertex modVerVtx, String elementTrail) + throws AAIException { + // Get the associated nodeType (Ie. aai-node-type / widget-type) for a model-ver. + // NOTE -- if the element points to a resource or service model, then we'll return the + // widget-type of the first element (crown widget) for that model. + String modelType = getModelTypeFromModelVer(modVerVtx, elementTrail); + if (modelType == null) { + String msg = + " Could not determine modelType in getModelVerTopWidgetType(). elementTrail = [" + + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + String thisElementNodeType = "?"; + if (modelType.equals("widget")) { + // NOTE: for models that have model-type = "widget", their child model-ver nodes will + // have "model-name" which maps directly to aai-node-type (all model-ver's under one + // model should start with the same widget-type, so we only need to look at one). + thisElementNodeType = modVerVtx.<String>property("model-name").orElse(null); + if ((thisElementNodeType == null) || thisElementNodeType.equals("")) { + String msg = + "Could not find model-name for the widget model pointed to by element at [" + + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + } else if (modelType.equals("resource") || modelType.equals("service")) { + Vertex relatedTopElementVtx = getTopElementForSvcOrResModelVer(modVerVtx, elementTrail); + Vertex relatedModVerVtx = + getModelVerThatElementRepresents(relatedTopElementVtx, elementTrail); + thisElementNodeType = relatedModVerVtx.<String>property("model-name").orElse(null); + if ((thisElementNodeType == null) || thisElementNodeType.equals("")) { + String msg = + "Could not find model-name for the widget model pointed to by element at [" + + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + } else { + String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + return thisElementNodeType; + + }// getModelVerTopWidgetType() + + /** + * Validate model. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVersionIdVal the model name version id + * @param apiVersion the api version + * @throws AAIException the AAI exception + */ + public void validateModel(String transId, String fromAppId, String modelVersionIdVal, + String apiVersion) throws AAIException { + + // Note - this will throw an exception if the model either can't be found, or if + // we can't figure out its topology map. + Vertex modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", + "model-version-id", modelVersionIdVal); + if (modelVerVtx == null) { + String msg = + " Could not find model-ver with modelVersionId = [" + modelVersionIdVal + "]."; + throw new AAIException("AAI_6114", msg); + } else { + Multimap<String, String> topoMap = + genTopoMap4ModelVer(transId, fromAppId, modelVerVtx, modelVersionIdVal); + String msg = " modelVer [" + modelVersionIdVal + "] topo multiMap looks like: \n[" + + topoMap + "]"; + System.out.println("INFO -- " + msg); + } + }// End validateModel() + + /** + * Validate named query. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param namedQueryUuid the named query uuid + * @param apiVersion the api version + * @throws AAIException the AAI exception + */ + public void validateNamedQuery(String transId, String fromAppId, String namedQueryUuid, + String apiVersion) throws AAIException { + + // Note - this will throw an exception if the named query either can't be found, or if + // we can't figure out its topology map. + Vertex nqVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query", "named-query-uuid", + namedQueryUuid); + + if (nqVtx == null) { + String msg = + " Could not find named-query with namedQueryUuid = [" + namedQueryUuid + "]."; + throw new AAIException("AAI_6114", msg); + } else { + // Multimap<String, String> topoMap = genTopoMap4NamedQ( "junkTransId", "junkFromAppId", + // graph, nqVtx, namedQueryUuid ); + // System.out.println("DEBUG -- for test only : --- "); + // System.out.println("DEBUG -- topomap = [" + topoMap + "]"); + } + + }// End validateNamedQuery() + + /** + * Show result set. + * + * @param resSet the res set + * @param levelCount the level count + */ + public void showResultSet(ResultSet resSet, int levelCount) { + + levelCount++; + String propsStr = ""; + for (int i = 1; i <= levelCount; i++) { + propsStr = propsStr + "-"; + } + if (resSet.getVert() == null) { + return; + } + String nt = resSet.getVert().<String>property(AAIProperties.NODE_TYPE).orElse(null); + propsStr = propsStr + "[" + nt + "] "; + + // propsStr = propsStr + " newDataDelFlag = " + resSet.getNewDataDelFlag() + ", trail = " + + // resSet.getLocationInModelSubGraph(); + // propsStr = propsStr + "limitDesc = [" + resSet.getPropertyLimitDesc() + "]"; + propsStr = propsStr + " trail = " + resSet.getLocationInModelSubGraph(); + + Map<String, Object> overrideHash = resSet.getPropertyOverRideHash(); + if (overrideHash != null && !overrideHash.isEmpty()) { + for (Map.Entry<String, Object> entry : overrideHash.entrySet()) { + String propName = entry.getKey(); + Object propVal = entry.getValue(); + propsStr = propsStr + " [" + propName + " = " + propVal + "]"; + } + } else { + Iterator<VertexProperty<Object>> pI = resSet.getVert().properties(); + while (pI.hasNext()) { + VertexProperty<Object> tp = pI.next(); + if (!tp.key().startsWith("aai") && !tp.key().equals("source-of-truth") + // && ! tp.key().equals("resource-version") + && !tp.key().startsWith("last-mod")) { + propsStr = propsStr + " [" + tp.key() + " = " + tp.value() + "]"; + } + } + } + // Show the "extra" lookup values too + Map<String, Object> extraPropHash = resSet.getExtraPropertyHash(); + if (extraPropHash != null && !extraPropHash.isEmpty()) { + for (Map.Entry<String, Object> entry : extraPropHash.entrySet()) { + String propName = entry.getKey(); + Object propVal = entry.getValue(); + propsStr = propsStr + " [" + propName + " = " + propVal.toString() + "]"; + } + } + + System.out.println(propsStr); + logger.info(propsStr); + + if (!resSet.getSubResultSet().isEmpty()) { + ListIterator<ResultSet> listItr = resSet.getSubResultSet().listIterator(); + while (listItr.hasNext()) { + showResultSet(listItr.next(), levelCount); + } + } + + }// end of showResultSet() + + private Iterator<Vertex> traverseIncidentEdges(EdgeType treeType, Vertex startV, + String connectedNodeType) throws AAIException { + return this.engine.getQueryBuilder(startV).createEdgeTraversal(treeType, startV, + loader.introspectorFromName(connectedNodeType)); + } + + private Iterator<Vertex> traverseIncidentEdges(EdgeType treeType, Vertex startV, + String... connectedNodeType) throws AAIException { + QueryBuilder[] builders = new QueryBuilder[connectedNodeType.length]; + for (int i = 0; i < connectedNodeType.length; i++) { + builders[i] = this.engine.getQueryBuilder(startV).createEdgeTraversal(EdgeType.TREE, + startV, loader.introspectorFromName(connectedNodeType[i])); + } + return this.engine.getQueryBuilder(startV).union(builders); + } + + private String addDBAliasedSuffix(String propName) { + return propName + AAIProperties.DB_ALIAS_SUFFIX; + } + + protected String getPropNameWithAliasIfNeeded(String nodeType, String propName) + throws AAIUnknownObjectException { + + String retPropName = propName; + if (loader.introspectorFromName(nodeType) + .getPropertyMetadata(propName, PropertyMetadata.DB_ALIAS).isPresent()) { + return propName + AAIProperties.DB_ALIAS_SUFFIX; + } + return retPropName; + } + +} diff --git a/aai-traversal/src/main/java/org/onap/aai/dbgraphgen/ResultSet.java b/aai-traversal/src/main/java/org/onap/aai/dbgraphgen/ResultSet.java index 2da0e0b..d50b978 100644 --- a/aai-traversal/src/main/java/org/onap/aai/dbgraphgen/ResultSet.java +++ b/aai-traversal/src/main/java/org/onap/aai/dbgraphgen/ResultSet.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -28,140 +28,131 @@ import org.apache.tinkerpop.gremlin.structure.Vertex; import org.onap.aai.dbgen.PropertyLimitDesc; public class ResultSet { - private Vertex vert; - private String newDataDelFlag; - private String doNotOutputFlag; - private String locationInModelSubGraph; - private List<ResultSet> subResultSet; - private PropertyLimitDesc propertyLimitDesc; - private Map<String,Object> propertyOverRideHash; - private Map<String,Object> extraPropertyHash; - - /** - * Instantiates a new result set. - */ - public ResultSet(){ - this.vert = null; - this.newDataDelFlag = ""; - this.doNotOutputFlag = ""; - this.locationInModelSubGraph = ""; - this.subResultSet = new ArrayList<>(); - this.propertyLimitDesc = null; - this.propertyOverRideHash = new HashMap<>(); - this.extraPropertyHash = new HashMap<>(); - } - - - public void setPropertyLimitDesc(PropertyLimitDesc pld) { - this.propertyLimitDesc = pld; - } - - /** - * Gets the vert. - * - * @return the vert - */ - public Vertex getVert(){ - return this.vert; - } - - /** - * Gets the sub result set. - * - * @return the sub result set - */ - public List<ResultSet> getSubResultSet(){ - return this.subResultSet; - } - - /** - * Gets the new data del flag. - * - * @return the new data del flag - */ - public String getNewDataDelFlag(){ - return this.newDataDelFlag; - } - - /** - * Gets the do not output flag. - * - * @return the do not output flag - */ - public String getDoNotOutputFlag(){ - return this.doNotOutputFlag; - } - - /** - * Gets the location in model sub graph. - * - * @return the location in model sub graph - */ - public String getLocationInModelSubGraph(){ - return this.locationInModelSubGraph; - } - - /** - * Gets the property limit desc. - * - * @return the property limit desc - */ - public PropertyLimitDesc getPropertyLimitDesc(){ - return this.propertyLimitDesc; - } - - /** - * Gets the property over ride hash. - * - * @return the property over ride hash - */ - public Map<String,Object> getPropertyOverRideHash(){ - return this.propertyOverRideHash; - } - - /** - * Gets the extra property hash. - * - * @return the extra property hash - */ - public Map<String,Object> getExtraPropertyHash(){ - return this.extraPropertyHash; - } - - - public void setVert(Vertex vert) { - this.vert = vert; - } - - - public void setNewDataDelFlag(String newDataDelFlag) { - this.newDataDelFlag = newDataDelFlag; - } - - - public void setDoNotOutputFlag(String doNotOutputFlag) { - this.doNotOutputFlag = doNotOutputFlag; - } - - - public void setLocationInModelSubGraph(String locationInModelSubGraph) { - this.locationInModelSubGraph = locationInModelSubGraph; - } - - - public void setSubResultSet(List<ResultSet> subResultSet) { - this.subResultSet = subResultSet; - } - - - public void setPropertyOverRideHash(Map<String, Object> propertyOverRideHash) { - this.propertyOverRideHash = propertyOverRideHash; - } - - - public void setExtraPropertyHash(Map<String, Object> extraPropertyHash) { - this.extraPropertyHash = extraPropertyHash; - } - + private Vertex vert; + private String newDataDelFlag; + private String doNotOutputFlag; + private String locationInModelSubGraph; + private List<ResultSet> subResultSet; + private PropertyLimitDesc propertyLimitDesc; + private Map<String, Object> propertyOverRideHash; + private Map<String, Object> extraPropertyHash; + + /** + * Instantiates a new result set. + */ + public ResultSet() { + this.vert = null; + this.newDataDelFlag = ""; + this.doNotOutputFlag = ""; + this.locationInModelSubGraph = ""; + this.subResultSet = new ArrayList<>(); + this.propertyLimitDesc = null; + this.propertyOverRideHash = new HashMap<>(); + this.extraPropertyHash = new HashMap<>(); + } + + public void setPropertyLimitDesc(PropertyLimitDesc pld) { + this.propertyLimitDesc = pld; + } + + /** + * Gets the vert. + * + * @return the vert + */ + public Vertex getVert() { + return this.vert; + } + + /** + * Gets the sub result set. + * + * @return the sub result set + */ + public List<ResultSet> getSubResultSet() { + return this.subResultSet; + } + + /** + * Gets the new data del flag. + * + * @return the new data del flag + */ + public String getNewDataDelFlag() { + return this.newDataDelFlag; + } + + /** + * Gets the do not output flag. + * + * @return the do not output flag + */ + public String getDoNotOutputFlag() { + return this.doNotOutputFlag; + } + + /** + * Gets the location in model sub graph. + * + * @return the location in model sub graph + */ + public String getLocationInModelSubGraph() { + return this.locationInModelSubGraph; + } + + /** + * Gets the property limit desc. + * + * @return the property limit desc + */ + public PropertyLimitDesc getPropertyLimitDesc() { + return this.propertyLimitDesc; + } + + /** + * Gets the property over ride hash. + * + * @return the property over ride hash + */ + public Map<String, Object> getPropertyOverRideHash() { + return this.propertyOverRideHash; + } + + /** + * Gets the extra property hash. + * + * @return the extra property hash + */ + public Map<String, Object> getExtraPropertyHash() { + return this.extraPropertyHash; + } + + public void setVert(Vertex vert) { + this.vert = vert; + } + + public void setNewDataDelFlag(String newDataDelFlag) { + this.newDataDelFlag = newDataDelFlag; + } + + public void setDoNotOutputFlag(String doNotOutputFlag) { + this.doNotOutputFlag = doNotOutputFlag; + } + + public void setLocationInModelSubGraph(String locationInModelSubGraph) { + this.locationInModelSubGraph = locationInModelSubGraph; + } + + public void setSubResultSet(List<ResultSet> subResultSet) { + this.subResultSet = subResultSet; + } + + public void setPropertyOverRideHash(Map<String, Object> propertyOverRideHash) { + this.propertyOverRideHash = propertyOverRideHash; + } + + public void setExtraPropertyHash(Map<String, Object> extraPropertyHash) { + this.extraPropertyHash = extraPropertyHash; + } } 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 1ca7c82..1dc8ac1 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -21,7 +21,19 @@ package org.onap.aai.dbgraphmap; import com.google.common.base.CaseFormat; import com.google.common.collect.Multimap; + import edu.emory.mathcs.backport.java.util.Collections; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.*; +import java.util.stream.Stream; + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.xml.bind.JAXBException; + import org.apache.commons.lang3.StringUtils; import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; @@ -63,17 +75,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.xml.bind.JAXBException; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.*; -import java.util.stream.Stream; - - - /** * Database Mapping class which acts as the middle man between the REST interface objects for the * Search namespace @@ -90,7 +91,8 @@ public class SearchGraph { private SchemaVersions schemaVersions; @Autowired - public SearchGraph(LoaderFactory loaderFactory, EdgeIngestor edgeIngestor, SchemaVersions schemaVersions) { + public SearchGraph(LoaderFactory loaderFactory, EdgeIngestor edgeIngestor, + SchemaVersions schemaVersions) { this.loaderFactory = loaderFactory; this.edgeIngestor = edgeIngestor; this.schemaVersions = schemaVersions; @@ -109,7 +111,8 @@ public class SearchGraph { genericQueryBuilder.getDbEngine().startTransaction(); if (genericQueryBuilder.getStartNodeType() == null) { - throw new AAIException("AAI_6120", "null start-node-type passed to the generic query"); + throw new AAIException("AAI_6120", + "null start-node-type passed to the generic query"); } if (genericQueryBuilder.getStartNodeKeyParams() == null) { @@ -121,25 +124,28 @@ public class SearchGraph { } if (genericQueryBuilder.getDepth() > 6) { - throw new AAIException("AAI_6120", "The maximum depth supported by the generic query is 6"); + throw new AAIException("AAI_6120", + "The maximum depth supported by the generic query is 6"); } final QueryBuilder queryBuilder; // there is an issue with service-instance - it is a unique node but still dependent // for now query it directly without attempting to craft a valid URI if (genericQueryBuilder.getStartNodeType().equalsIgnoreCase("service-instance") - && genericQueryBuilder.getStartNodeKeyParams().size() == 1) { - genericQueryBuilder.getLoader().introspectorFromName(genericQueryBuilder.getStartNodeType()); + && genericQueryBuilder.getStartNodeKeyParams().size() == 1) { + genericQueryBuilder.getLoader() + .introspectorFromName(genericQueryBuilder.getStartNodeType()); // Build a hash with keys to uniquely identify the start Node String keyName; String keyValue; QueryBuilder builder = genericQueryBuilder.getDbEngine().getQueryBuilder() - .getVerticesByIndexedProperty(AAIProperties.NODE_TYPE, "service-instance"); + .getVerticesByIndexedProperty(AAIProperties.NODE_TYPE, "service-instance"); for (String keyData : genericQueryBuilder.getStartNodeKeyParams()) { int colonIndex = keyData.indexOf(':'); if (colonIndex <= 0) { - throw new AAIException("AAI_6120", "Bad key param passed in: [" + keyData + "]"); + throw new AAIException("AAI_6120", + "Bad key param passed in: [" + keyData + "]"); } else { keyName = keyData.substring(0, colonIndex).split("\\.")[1]; keyValue = keyData.substring(colonIndex + 1); @@ -150,18 +156,20 @@ public class SearchGraph { queryBuilder = builder; } else { URI uri = craftUriFromQueryParams(genericQueryBuilder.getLoader(), - genericQueryBuilder.getStartNodeType(), genericQueryBuilder.getStartNodeKeyParams()); - queryBuilder = - genericQueryBuilder.getDbEngine().getQueryBuilder().createQueryFromURI(uri).getQueryBuilder(); + genericQueryBuilder.getStartNodeType(), + genericQueryBuilder.getStartNodeKeyParams()); + queryBuilder = genericQueryBuilder.getDbEngine().getQueryBuilder() + .createQueryFromURI(uri).getQueryBuilder(); } List<Vertex> results = queryBuilder.toList(); if (results.isEmpty()) { - String errorMessage = String.format("No Node of type %s ", genericQueryBuilder.getStartNodeType(), - " found for properties: %s", genericQueryBuilder.getStartNodeKeyParams().toString()); + String errorMessage = String.format("No Node of type %s ", + genericQueryBuilder.getStartNodeType(), " found for properties: %s", + genericQueryBuilder.getStartNodeKeyParams().toString()); throw new AAIException("AAI_6114", errorMessage); } else if (results.size() > 1) { String detail = "More than one Node found by getUniqueNode for params: " - + genericQueryBuilder.getStartNodeKeyParams().toString() + "\n"; + + genericQueryBuilder.getStartNodeKeyParams().toString() + "\n"; throw new AAIException("AAI_6112", detail); } @@ -170,34 +178,39 @@ public class SearchGraph { Collection<Vertex> ver = new HashSet<>(); List<Vertex> queryResults; GraphTraversalSource traversalSource = - genericQueryBuilder.getDbEngine().asAdmin().getReadOnlyTraversalSource(); + genericQueryBuilder.getDbEngine().asAdmin().getReadOnlyTraversalSource(); GraphTraversal<Vertex, Vertex> traversal; - if (genericQueryBuilder.getIncludeNodeTypes().contains(genericQueryBuilder.getStartNodeType()) - || genericQueryBuilder.getDepth() == 0 || genericQueryBuilder.getIncludeNodeTypes().contains("all")) + if (genericQueryBuilder.getIncludeNodeTypes() + .contains(genericQueryBuilder.getStartNodeType()) + || genericQueryBuilder.getDepth() == 0 + || genericQueryBuilder.getIncludeNodeTypes().contains("all")) ver.add(startNode); // Now look for a node of includeNodeType within a given depth - traversal = traversalSource.withSideEffect("x", ver).V(startNode).times(genericQueryBuilder.getDepth()) - .repeat(__.both().store("x")).cap("x").unfold(); + traversal = traversalSource.withSideEffect("x", ver).V(startNode) + .times(genericQueryBuilder.getDepth()).repeat(__.both().store("x")).cap("x") + .unfold(); if (!genericQueryBuilder.getIncludeNodeTypes().contains("all")) { - traversal.where(__.has(AAIProperties.NODE_TYPE, P.within(genericQueryBuilder.getIncludeNodeTypes()))); + traversal.where(__.has(AAIProperties.NODE_TYPE, + P.within(genericQueryBuilder.getIncludeNodeTypes()))); } queryResults = traversal.toList(); - if (queryResults.isEmpty()) { - AAIException aaiException = new AAIException("AAI_6114", "No nodes found - apipe was null/empty"); + AAIException aaiException = + new AAIException("AAI_6114", "No nodes found - apipe was null/empty"); ErrorLogHelper.logException(aaiException); } else { Introspector searchResults = createSearchResults(genericQueryBuilder.getLoader(), - genericQueryBuilder.getUrlBuilder(), queryResults); + genericQueryBuilder.getUrlBuilder(), queryResults); - String outputMediaType = getMediaType(genericQueryBuilder.getHeaders().getAcceptableMediaTypes()); + String outputMediaType = + getMediaType(genericQueryBuilder.getHeaders().getAcceptableMediaTypes()); org.onap.aai.introspection.MarshallerProperties properties = - new org.onap.aai.introspection.MarshallerProperties.Builder( - org.onap.aai.restcore.MediaType.getEnum(outputMediaType)).build(); + new org.onap.aai.introspection.MarshallerProperties.Builder( + org.onap.aai.restcore.MediaType.getEnum(outputMediaType)).build(); result = searchResults.marshal(properties); response = Response.ok().entity(result).build(); @@ -225,8 +238,8 @@ public class SearchGraph { return response; } - private URI craftUriFromQueryParams(Loader loader, String startNodeType, List<String> startNodeKeyParams) - throws UnsupportedEncodingException, AAIException { + private URI craftUriFromQueryParams(Loader loader, String startNodeType, + List<String> startNodeKeyParams) throws UnsupportedEncodingException, AAIException { Introspector relationship = loader.introspectorFromName("relationship"); relationship.setValue("related-to", startNodeType); @@ -271,40 +284,48 @@ public class SearchGraph { Introspector target; if (StringUtils.isBlank(nodesQuery.getTargetNodeType())) { - throw new AAIException("AAI_6120", "null or empty target-node-type passed to the node query"); + throw new AAIException("AAI_6120", + "null or empty target-node-type passed to the node query"); } try { - target = nodesQuery.getLoader().introspectorFromName(nodesQuery.getTargetNodeType()); + target = + nodesQuery.getLoader().introspectorFromName(nodesQuery.getTargetNodeType()); } catch (AAIUnknownObjectException e) { - throw new AAIException("AAI_6115", - "Unrecognized nodeType [" + nodesQuery.getTargetNodeType() + "] passed to node query."); + throw new AAIException("AAI_6115", "Unrecognized nodeType [" + + nodesQuery.getTargetNodeType() + "] passed to node query."); } - if (nodesQuery.getFilterParams().isEmpty() && nodesQuery.getEdgeFilterParams().isEmpty()) { - // For now, it's ok to pass no filter params. We'll just return ALL the nodes of the requested type. + if (nodesQuery.getFilterParams().isEmpty() + && nodesQuery.getEdgeFilterParams().isEmpty()) { + // For now, it's ok to pass no filter params. We'll just return ALL the nodes of the + // requested type. LOGGER.debug("No filters passed to the node query"); } - GraphTraversal<Vertex, Vertex> traversal = nodesQuery.getDbEngine().asAdmin().getReadOnlyTraversalSource() - .V().has(AAIProperties.NODE_TYPE, nodesQuery.getTargetNodeType()); + GraphTraversal<Vertex, Vertex> traversal = + nodesQuery.getDbEngine().asAdmin().getReadOnlyTraversalSource().V() + .has(AAIProperties.NODE_TYPE, nodesQuery.getTargetNodeType()); for (String filter : nodesQuery.getFilterParams()) { String[] pieces = filter.split(":"); if (pieces.length < 2) { - throw new AAIException("AAI_6120", "bad filter passed to node query: [" + filter + "]"); + throw new AAIException("AAI_6120", + "bad filter passed to node query: [" + filter + "]"); } else { String propName = this.findDbPropName(target, pieces[0]); String filterType = pieces[1]; if (filterType.equals(EQUALS)) { if (pieces.length < 3) { - throw new AAIException("AAI_6120", "No value passed for filter: [" + filter + "]"); + throw new AAIException("AAI_6120", + "No value passed for filter: [" + filter + "]"); } String value = "?"; if (pieces.length == 3) { value = pieces[2]; } else { // length > 3 - // When a ipv6 address comes in as a value, it has colons in it which require us to + // When a ipv6 address comes in as a value, it has colons in it which + // require us to // pull the "value" off the end of the filter differently int startPos4Value = propName.length() + filterType.length() + 3; value = filter.substring(startPos4Value); @@ -312,13 +333,15 @@ public class SearchGraph { traversal.has(propName, value); } else if (filterType.equals(DOES_NOT_EQUAL)) { if (pieces.length < 3) { - throw new AAIException("AAI_6120", "No value passed for filter: [" + filter + "]"); + throw new AAIException("AAI_6120", + "No value passed for filter: [" + filter + "]"); } String value = "?"; if (pieces.length == 3) { value = pieces[2]; } else { // length > 3 - // When a ipv6 address comes in as a value, it has colons in it which require us to + // When a ipv6 address comes in as a value, it has colons in it which + // require us to // pull the "value" off the end of the filter differently int startPos4Value = propName.length() + filterType.length() + 3; value = filter.substring(startPos4Value); @@ -329,7 +352,8 @@ public class SearchGraph { } else if (filterType.equals(DOES_NOT_EXIST)) { traversal.hasNot(propName); } else { - throw new AAIException("AAI_6120", "bad filterType passed: [" + filterType + "]"); + throw new AAIException("AAI_6120", + "bad filterType passed: [" + filterType + "]"); } } } @@ -337,7 +361,8 @@ public class SearchGraph { if (!nodesQuery.getEdgeFilterParams().isEmpty()) { // edge-filter=pserver:EXISTS: OR pserver:EXISTS:hostname:XXX // edge-filter=pserver:DOES-NOT-EXIST: OR pserver:DOES-NOT-EXIST:hostname:XXX - String filter = nodesQuery.getEdgeFilterParams().get(0); // we process and allow only one edge filter + String filter = nodesQuery.getEdgeFilterParams().get(0); // we process and allow + // only one edge filter // for now String[] pieces = filter.split(":"); if (pieces.length < 2 || pieces.length == 3 || pieces.length > 4) { @@ -347,13 +372,14 @@ public class SearchGraph { String filterType = pieces[1].toUpperCase(); Introspector otherNode; if (!filterType.equals(EXISTS) && !filterType.equals(DOES_NOT_EXIST)) { - throw new AAIException("AAI_6120", "bad filterType passed: [" + filterType + "]"); + throw new AAIException("AAI_6120", + "bad filterType passed: [" + filterType + "]"); } try { otherNode = nodesQuery.getLoader().introspectorFromName(nodeType); } catch (AAIUnknownObjectException e) { throw new AAIException("AAI_6115", - "Unrecognized nodeType [" + nodeType + "] passed to node query."); + "Unrecognized nodeType [" + nodeType + "] passed to node query."); } String propName = null; String propValue = null; @@ -385,12 +411,13 @@ public class SearchGraph { List<Vertex> results = traversal.toList(); Introspector searchResults = - createSearchResults(nodesQuery.getLoader(), nodesQuery.getUrlBuilder(), results); + createSearchResults(nodesQuery.getLoader(), nodesQuery.getUrlBuilder(), results); - String outputMediaType = getMediaType(nodesQuery.getHeaders().getAcceptableMediaTypes()); + String outputMediaType = + getMediaType(nodesQuery.getHeaders().getAcceptableMediaTypes()); org.onap.aai.introspection.MarshallerProperties properties = - new org.onap.aai.introspection.MarshallerProperties.Builder( - org.onap.aai.restcore.MediaType.getEnum(outputMediaType)).build(); + new org.onap.aai.introspection.MarshallerProperties.Builder( + org.onap.aai.restcore.MediaType.getEnum(outputMediaType)).build(); result = searchResults.marshal(properties); response = Response.ok().entity(result).build(); @@ -415,8 +442,8 @@ public class SearchGraph { return response; } - protected Introspector createSearchResults(Loader loader, UrlBuilder urlBuilder, List<Vertex> results) - throws AAIUnknownObjectException { + protected Introspector createSearchResults(Loader loader, UrlBuilder urlBuilder, + List<Vertex> results) throws AAIUnknownObjectException { Introspector searchResults = loader.introspectorFromName("search-results"); List<Object> resultDataList = searchResults.getValue("result-data"); Stream<Vertex> stream; @@ -461,7 +488,6 @@ public class SearchGraph { } } - /** * Gets the edge label. * @@ -471,8 +497,7 @@ public class SearchGraph { * @throws EdgeRuleNotFoundException The Edge Rule Not Found Exception */ public String[] getEdgeLabel(String targetNodeType, String nodeType) - throws EdgeRuleNotFoundException { - + throws EdgeRuleNotFoundException { EdgeRuleQuery query = new EdgeRuleQuery.Builder(targetNodeType, nodeType).build(); Multimap<String, EdgeRule> edgeRules = edgeIngestor.getRules(query); @@ -480,7 +505,6 @@ public class SearchGraph { return edgeRules.values().stream().map(EdgeRule::getLabel).toArray(String[]::new); } - /** * Run named query. * @@ -493,7 +517,7 @@ public class SearchGraph { * @throws AAIException the AAI exception */ public Response runNamedQuery(String fromAppId, String transId, String queryParameters, - AAIExtensionMap aaiExtMap) throws AAIException { + AAIExtensionMap aaiExtMap) throws AAIException { Introspector inventoryItems; boolean success = true; @@ -501,15 +525,16 @@ public class SearchGraph { try { MoxyLoader loader = (MoxyLoader) loaderFactory.createLoaderForVersion(ModelType.MOXY, - schemaVersions.getDefaultVersion()); + schemaVersions.getDefaultVersion()); DynamicJAXBContext jaxbContext = loader.getJAXBContext(); dbEngine = new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader); - DBSerializer serializer = - new DBSerializer(schemaVersions.getDefaultVersion(), dbEngine, ModelType.MOXY, fromAppId); + DBSerializer serializer = new DBSerializer(schemaVersions.getDefaultVersion(), dbEngine, + ModelType.MOXY, fromAppId); ModelBasedProcessing processor = new ModelBasedProcessing(loader, dbEngine, serializer); dbEngine.startTransaction(); - org.onap.aai.restcore.MediaType mediaType = org.onap.aai.restcore.MediaType.APPLICATION_JSON_TYPE; + org.onap.aai.restcore.MediaType mediaType = + org.onap.aai.restcore.MediaType.APPLICATION_JSON_TYPE; String contentType = aaiExtMap.getHttpServletRequest().getContentType(); if (contentType != null && contentType.contains("application/xml")) { mediaType = org.onap.aai.restcore.MediaType.APPLICATION_XML_TYPE; @@ -520,7 +545,8 @@ public class SearchGraph { } DynamicEntity modelAndNamedQuerySearch = (DynamicEntity) loader - .unmarshal("ModelAndNamedQuerySearch", queryParameters, mediaType).getUnderlyingObject(); + .unmarshal("ModelAndNamedQuerySearch", queryParameters, mediaType) + .getUnderlyingObject(); if (modelAndNamedQuerySearch == null) { throw new AAIException("AAI_5105"); } @@ -538,7 +564,8 @@ public class SearchGraph { namedQueryLookupHash.put("named-query-name", namedQuery.get("namedQueryName")); } if (namedQuery.isSet("namedQueryVersion")) { - namedQueryLookupHash.put("named-query-version", namedQuery.get("namedQueryVersion")); + namedQueryLookupHash.put("named-query-version", + namedQuery.get("namedQueryVersion")); } } @@ -546,7 +573,7 @@ public class SearchGraph { DbMethHelper dbMethHelper = new DbMethHelper(loader, dbEngine); List<Vertex> namedQueryVertices = - dbMethHelper.locateUniqueVertices("named-query", namedQueryLookupHash); + dbMethHelper.locateUniqueVertices("named-query", namedQueryLookupHash); for (Vertex vert : namedQueryVertices) { namedQueryUuid = vert.<String>property("named-query-uuid").orElse(null); // there should only be one, we'll pick the first if not @@ -563,15 +590,16 @@ public class SearchGraph { List<Map<String, Object>> startNodeFilterHash = new ArrayList<>(); mapInstanceFilters(modelAndNamedQuerySearch.get("instanceFilters"), startNodeFilterHash, - jaxbContext); + jaxbContext); Map<String, Object> secondaryFilterHash = new HashMap<>(); mapSecondaryFilters(modelAndNamedQuerySearch.get("secondaryFilts"), secondaryFilterHash, - jaxbContext); + jaxbContext); - List<ResultSet> resultSet = processor.queryByNamedQuery(transId, fromAppId, namedQueryUuid, - startNodeFilterHash, aaiExtMap.getApiVersion(), secondaryFilterCutPoint, secondaryFilterHash); + List<ResultSet> resultSet = + processor.queryByNamedQuery(transId, fromAppId, namedQueryUuid, startNodeFilterHash, + aaiExtMap.getApiVersion(), secondaryFilterCutPoint, secondaryFilterHash); inventoryItems = loader.introspectorFromName("inventory-response-items"); @@ -613,24 +641,23 @@ public class SearchGraph { * @throws UnsupportedEncodingException the unsupported encoding exception */ public Response executeModelOperation(String fromAppId, String transId, String queryParameters, - boolean isDelete, AAIExtensionMap aaiExtMap) - throws AAIException { + boolean isDelete, AAIExtensionMap aaiExtMap) throws AAIException { Response response; boolean success = true; TransactionalGraphEngine dbEngine = null; try { MoxyLoader loader = (MoxyLoader) loaderFactory.createLoaderForVersion(ModelType.MOXY, - schemaVersions.getDefaultVersion()); + schemaVersions.getDefaultVersion()); DynamicJAXBContext jaxbContext = loader.getJAXBContext(); dbEngine = new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader); - DBSerializer serializer = - new DBSerializer(schemaVersions.getDefaultVersion(), dbEngine, ModelType.MOXY, fromAppId); + DBSerializer serializer = new DBSerializer(schemaVersions.getDefaultVersion(), dbEngine, + ModelType.MOXY, fromAppId); ModelBasedProcessing processor = new ModelBasedProcessing(loader, dbEngine, serializer); dbEngine.startTransaction(); - - org.onap.aai.restcore.MediaType mediaType = org.onap.aai.restcore.MediaType.APPLICATION_JSON_TYPE; + org.onap.aai.restcore.MediaType mediaType = + org.onap.aai.restcore.MediaType.APPLICATION_JSON_TYPE; String contentType = aaiExtMap.getHttpServletRequest().getContentType(); if (contentType != null && contentType.contains("application/xml")) { mediaType = org.onap.aai.restcore.MediaType.APPLICATION_XML_TYPE; @@ -641,12 +668,12 @@ public class SearchGraph { } DynamicEntity modelAndNamedQuerySearch = (DynamicEntity) loader - .unmarshal("ModelAndNamedQuerySearch", queryParameters, mediaType).getUnderlyingObject(); + .unmarshal("ModelAndNamedQuerySearch", queryParameters, mediaType) + .getUnderlyingObject(); if (modelAndNamedQuerySearch == null) { throw new AAIException("AAI_5105"); } - String modelVersionId = null; String modelName = null; String modelInvariantId = null; @@ -663,7 +690,8 @@ public class SearchGraph { // 2. model-invariant-id (previously model-id) + model-version // 3. model-name + model-version - // we will support both using the OverloadedModel object in the v9 oxm. This allows us to unmarshal + // we will support both using the OverloadedModel object in the v9 oxm. This allows us + // to unmarshal // either an old-style model or new-style model + model-ver object if (modelAndNamedQuerySearch.isSet("queryParameters")) { DynamicEntity qp = modelAndNamedQuerySearch.get("queryParameters"); @@ -715,12 +743,13 @@ public class SearchGraph { List<Map<String, Object>> startNodeFilterHash = new ArrayList<>(); - String resourceVersion = mapInstanceFilters( modelAndNamedQuerySearch.get("instanceFilters"), - startNodeFilterHash, jaxbContext); + String resourceVersion = mapInstanceFilters( + modelAndNamedQuerySearch.get("instanceFilters"), startNodeFilterHash, jaxbContext); if (isDelete) { - List<ResultSet> resultSet = processor.queryByModel(transId, fromAppId, modelVersionId, modelInvariantId, + List<ResultSet> resultSet = + processor.queryByModel(transId, fromAppId, modelVersionId, modelInvariantId, modelName, topNodeType, startNodeFilterHash, aaiExtMap.getApiVersion()); unpackResultSet(resultSet, dbEngine, loader, serializer); @@ -730,8 +759,9 @@ public class SearchGraph { Vertex firstVert = rs.getVert(); String restURI = serializer.getURIForVertex(firstVert).toString(); String notificationVersion = schemaVersions.getDefaultVersion().toString(); - Map<String, String> delResult = processor.runDeleteByModel(transId, fromAppId, modelVersionId, - topNodeType, startNodeFilterHash.get(0), aaiExtMap.getApiVersion(), resourceVersion); + Map<String, String> delResult = + processor.runDeleteByModel(transId, fromAppId, modelVersionId, topNodeType, + startNodeFilterHash.get(0), aaiExtMap.getApiVersion(), resourceVersion); String resultStr = ""; for (Map.Entry<String, String> ent : delResult.entrySet()) { @@ -744,10 +774,12 @@ public class SearchGraph { response = Response.ok(resultStr.trim()).build(); } else { - List<ResultSet> resultSet = processor.queryByModel(transId, fromAppId, modelVersionId, modelInvariantId, + List<ResultSet> resultSet = + processor.queryByModel(transId, fromAppId, modelVersionId, modelInvariantId, modelName, topNodeType, startNodeFilterHash, aaiExtMap.getApiVersion()); - Introspector inventoryItems = loader.introspectorFromName("inventory-response-items"); + Introspector inventoryItems = + loader.introspectorFromName("inventory-response-items"); List<Object> invItemList = unpackResultSet(resultSet, dbEngine, loader, serializer); @@ -786,10 +818,10 @@ public class SearchGraph { org.onap.aai.introspection.MarshallerProperties properties; if (isJson) { properties = new org.onap.aai.introspection.MarshallerProperties.Builder( - org.onap.aai.restcore.MediaType.APPLICATION_JSON_TYPE).build(); + org.onap.aai.restcore.MediaType.APPLICATION_JSON_TYPE).build(); } else { properties = new org.onap.aai.introspection.MarshallerProperties.Builder( - org.onap.aai.restcore.MediaType.APPLICATION_XML_TYPE).build(); + org.onap.aai.restcore.MediaType.APPLICATION_XML_TYPE).build(); } String marshalledObj = obj.marshal(properties); @@ -804,14 +836,15 @@ public class SearchGraph { * @param jaxbContext the jaxb context * @return the string */ - private String mapInstanceFilters(DynamicEntity instanceFilters, List<Map<String, Object>> startNodeFilterHash, - DynamicJAXBContext jaxbContext) { + private String mapInstanceFilters(DynamicEntity instanceFilters, + List<Map<String, Object>> startNodeFilterHash, DynamicJAXBContext jaxbContext) { if (instanceFilters == null || !instanceFilters.isSet("instanceFilter")) { return null; } @SuppressWarnings("unchecked") - List<DynamicEntity> instanceFilter = (ArrayList<DynamicEntity>) instanceFilters.get("instanceFilter"); + List<DynamicEntity> instanceFilter = + (ArrayList<DynamicEntity>) instanceFilters.get("instanceFilter"); String resourceVersion = null; for (DynamicEntity instFilt : instanceFilter) { @@ -829,8 +862,9 @@ public class SearchGraph { // hyphencase the prop and throw it on the hash if (anyEnt.isSet(propName)) { thisNodeFilterHash.put( - nodeType + "." + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, propName), - anyEnt.get(propName)); + nodeType + "." + + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, propName), + anyEnt.get(propName)); if (propName.equals("resourceVersion") && resourceVersion == null) { resourceVersion = (String) anyEnt.get(propName); } @@ -850,14 +884,15 @@ public class SearchGraph { * @param jaxbContext the jaxb context * @return the string */ - private void mapSecondaryFilters(DynamicEntity secondaryFilts, Map<String, Object> secondaryFilterHash, - DynamicJAXBContext jaxbContext) { + private void mapSecondaryFilters(DynamicEntity secondaryFilts, + Map<String, Object> secondaryFilterHash, DynamicJAXBContext jaxbContext) { if (secondaryFilts == null || !secondaryFilts.isSet("secondaryFilt")) { return; } @SuppressWarnings("unchecked") - List<DynamicEntity> secondaryFilter = (ArrayList<DynamicEntity>) secondaryFilts.get("secondaryFilt"); + List<DynamicEntity> secondaryFilter = + (ArrayList<DynamicEntity>) secondaryFilts.get("secondaryFilt"); for (DynamicEntity secondaryFilt : secondaryFilter) { List<DynamicEntity> any = secondaryFilt.get("any"); @@ -874,8 +909,9 @@ public class SearchGraph { // hyphencase the prop and throw it on the hash if (anyEnt.isSet(propName)) { secondaryFilterHash.put( - nodeType + "." + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, propName), - anyEnt.get(propName)); + nodeType + "." + + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, propName), + anyEnt.get(propName)); } } } @@ -892,12 +928,12 @@ public class SearchGraph { * @param aaiExtMap the aai ext map * @return the dynamic entity */ - private DynamicEntity remapInventoryItems(DynamicEntity invResultItem, DynamicJAXBContext jaxbContext, - Map<String, String> includeTheseVertices, Map<Object, String> objectToVertMap, AAIExtensionMap aaiExtMap) { - + private DynamicEntity remapInventoryItems(DynamicEntity invResultItem, + DynamicJAXBContext jaxbContext, Map<String, String> includeTheseVertices, + Map<Object, String> objectToVertMap, AAIExtensionMap aaiExtMap) { - DynamicEntity inventoryItem = jaxbContext - .newDynamicEntity("inventory.aai.onap.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItem"); + DynamicEntity inventoryItem = jaxbContext.newDynamicEntity( + "inventory.aai.onap.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItem"); Object item = invResultItem.get("item"); inventoryItem.set("modelName", invResultItem.get("modelName")); inventoryItem.set("item", item); @@ -909,16 +945,17 @@ public class SearchGraph { vertexId = objectToVertMap.get(item); } - if (includeTheseVertices.containsKey(vertexId) && invResultItem.isSet("inventoryResponseItems")) { + if (includeTheseVertices.containsKey(vertexId) + && invResultItem.isSet("inventoryResponseItems")) { List<DynamicEntity> invItemList = new ArrayList<>(); DynamicEntity inventoryItems = jaxbContext.newDynamicEntity( - "inventory.aai.att.com." + aaiExtMap.getApiVersion() + ".InventoryResponseItems"); + "inventory.aai.att.com." + aaiExtMap.getApiVersion() + ".InventoryResponseItems"); DynamicEntity subInventoryResponseItems = invResultItem.get("inventoryResponseItems"); List<DynamicEntity> subInventoryResponseItemList = - subInventoryResponseItems.get("inventoryResponseItem"); + subInventoryResponseItems.get("inventoryResponseItem"); for (DynamicEntity ent : subInventoryResponseItemList) { - DynamicEntity invItem = - remapInventoryItems(ent, jaxbContext, includeTheseVertices, objectToVertMap, aaiExtMap); + DynamicEntity invItem = remapInventoryItems(ent, jaxbContext, includeTheseVertices, + objectToVertMap, aaiExtMap); if (invItem != null) { invItemList.add(invItem); } @@ -939,8 +976,9 @@ public class SearchGraph { * @return the array list - should return list of inventoryItems * @throws AAIException The AAI Exception */ - private List<Object> unpackResultSet(List<ResultSet> resultSetList, TransactionalGraphEngine engine, Loader loader, - DBSerializer serializer) throws AAIException { + private List<Object> unpackResultSet(List<ResultSet> resultSetList, + TransactionalGraphEngine engine, Loader loader, DBSerializer serializer) + throws AAIException { List<Object> resultList = new ArrayList<>(); @@ -965,7 +1003,8 @@ public class SearchGraph { if (resultSet.getExtraPropertyHash() != null) { Map<String, Object> extraProperties = resultSet.getExtraPropertyHash(); - Introspector extraPropertiesEntity = loader.introspectorFromName("extra-properties"); + Introspector extraPropertiesEntity = + loader.introspectorFromName("extra-properties"); List<Object> extraPropsList = extraPropertiesEntity.getValue("extra-property"); @@ -973,7 +1012,8 @@ public class SearchGraph { String propName = ent.getKey(); Object propVal = ent.getValue(); - Introspector extraPropEntity = loader.introspectorFromName("extra-property"); + Introspector extraPropEntity = + loader.introspectorFromName("extra-property"); extraPropEntity.setValue("property-name", propName); extraPropEntity.setValue("property-value", propVal); @@ -981,11 +1021,13 @@ public class SearchGraph { extraPropsList.add(extraPropEntity.getUnderlyingObject()); } - inventoryItem.setValue("extra-properties", extraPropertiesEntity.getUnderlyingObject()); + inventoryItem.setValue("extra-properties", + extraPropertiesEntity.getUnderlyingObject()); } try { - serializer.dbToObject(Collections.singletonList(vert), thisObj, 0, true, "false"); + serializer.dbToObject(Collections.singletonList(vert), thisObj, 0, true, + "false"); } catch (UnsupportedEncodingException e1) { throw new AAIException("AAI_5105"); } @@ -1001,7 +1043,8 @@ public class SearchGraph { filterProperties(thisObj, emptyPropertyOverRideHash); } else if (PropertyLimitDesc.SHOW_ALL.equals(propertyLimitDesc)) { // keep everything - } else if (PropertyLimitDesc.SHOW_NAME_AND_KEYS_ONLY.equals(propertyLimitDesc)) { + } else if (PropertyLimitDesc.SHOW_NAME_AND_KEYS_ONLY + .equals(propertyLimitDesc)) { HashMap<String, Object> keysAndNamesPropHash = new HashMap<>(); for (String key : thisObj.getAllKeys()) { @@ -1017,8 +1060,10 @@ public class SearchGraph { filterProperties(thisObj, keysAndNamesPropHash); } } else { - if (resultSet.getPropertyOverRideHash() != null && resultSet.getPropertyOverRideHash().size() > 0) { - Map<String, Object> propertyOverRideHash = resultSet.getPropertyOverRideHash(); + if (resultSet.getPropertyOverRideHash() != null + && resultSet.getPropertyOverRideHash().size() > 0) { + Map<String, Object> propertyOverRideHash = + resultSet.getPropertyOverRideHash(); if (propertyOverRideHash.containsKey("persona-model-id")) { propertyOverRideHash.remove("persona-model-id"); propertyOverRideHash.put("model-invariant-id", null); @@ -1037,25 +1082,32 @@ public class SearchGraph { String modelName = null; try { - // Try to get the modelName if we can. Otherwise, do not fail, just return what we have already. + // Try to get the modelName if we can. Otherwise, do not fail, just return + // what we have already. String modelInvariantIdLocal = - vert.<String>property("model-invariant-id-local").orElse(null); // this one - // points at a - // model + vert.<String>property("model-invariant-id-local").orElse(null); // this + // one + // points + // at a + // model String modelVersionIdLocal = - vert.<String>property("model-version-id-local").orElse(null); // this one - // points at a - // model-ver + vert.<String>property("model-version-id-local").orElse(null); // this + // one + // points + // at a + // model-ver if ((modelInvariantIdLocal != null && modelVersionIdLocal != null) - && (modelInvariantIdLocal.length() > 0 && modelVersionIdLocal.length() > 0)) { + && (modelInvariantIdLocal.length() > 0 + && modelVersionIdLocal.length() > 0)) { Introspector modelVer = loader.introspectorFromName("model-ver"); modelVer.setValue("model-version-id", modelVersionIdLocal); QueryBuilder builder = engine.getQueryBuilder().createDBQuery(modelVer); List<Vertex> modelVerVerts = builder.toList(); if ((modelVerVerts != null) && (modelVerVerts.size() == 1)) { Vertex modelVerVert = modelVerVerts.get(0); - modelName = modelVerVert.<String>property("model-name").orElse(null); + modelName = + modelVerVert.<String>property("model-name").orElse(null); if (modelName != null && modelName.length() > 0) { inventoryItem.setValue("model-name", modelName); } @@ -1069,11 +1121,12 @@ public class SearchGraph { if (resultSet.getSubResultSet() != null) { List<ResultSet> subResultSet = resultSet.getSubResultSet(); if (subResultSet != null && !subResultSet.isEmpty()) { - List<Object> res = unpackResultSet(subResultSet, engine, loader, serializer); + List<Object> res = + unpackResultSet(subResultSet, engine, loader, serializer); if (!res.isEmpty()) { inventoryItems.setValue("inventory-response-item", res); inventoryItem.setValue("inventory-response-items", - inventoryItems.getUnderlyingObject()); + inventoryItems.getUnderlyingObject()); } } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java index f70febf..92c12b5 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/AAIContainerFilter.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -23,19 +23,19 @@ import java.util.UUID; import org.onap.aai.util.FormatDate; -public abstract class AAIContainerFilter { - - protected String genDate() { - FormatDate fd = new FormatDate("YYMMdd-HH:mm:ss:SSS"); - return fd.getDateTime(); - } - - protected boolean isValidUUID(String transId) { - try { - UUID.fromString(transId); - } catch (IllegalArgumentException e) { - return false; - } - return true; - } +public abstract class AAIContainerFilter { + + protected String genDate() { + FormatDate fd = new FormatDate("YYMMdd-HH:mm:ss:SSS"); + return fd.getDateTime(); + } + + protected boolean isValidUUID(String transId) { + try { + UUID.fromString(transId); + } catch (IllegalArgumentException e) { + return false; + } + return true; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java index f27e4f2..22c8234 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/AAIHeaderProperties.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -21,20 +21,21 @@ package org.onap.aai.interceptors; public final class AAIHeaderProperties { - public static final String REQUEST_CONTEXT = "aai-request-context"; + public static final String REQUEST_CONTEXT = "aai-request-context"; - public static final String HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override"; + public static final String HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override"; - public static final String TRANSACTION_ID = "X-TransactionId"; + public static final String TRANSACTION_ID = "X-TransactionId"; - public static final String FROM_APP_ID = "X-FromAppId"; + public static final String FROM_APP_ID = "X-FromAppId"; - public static final String AAI_TX_ID = "X-AAI-TXID"; + public static final String AAI_TX_ID = "X-AAI-TXID"; - public static final String AAI_REQUEST = "X-REQUEST"; + public static final String AAI_REQUEST = "X-REQUEST"; - public static final String AAI_REQUEST_TS = "X-REQUEST-TS"; + public static final String AAI_REQUEST_TS = "X-REQUEST-TS"; - private AAIHeaderProperties(){} + private AAIHeaderProperties() { + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/package-info.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/package-info.java index ee9c334..15a997a 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/package-info.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/package-info.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -26,11 +26,11 @@ * * <pre> * <code> - * @Priority(AAIRequestFilterPriority.YOUR_PRIORITY) + * @Priority(AAIRequestFilterPriority.YOUR_PRIORITY) * public class YourInterceptor extends AAIContainerFilter implements ContainerRequestFilter { * * } * </code> * </pre> */ -package org.onap.aai.interceptors;
\ No newline at end of file +package org.onap.aai.interceptors; diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java index ccf89fc..cf899c1 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/post/AAIResponseFilterPriority.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -26,13 +26,14 @@ package org.onap.aai.interceptors.post; * and INVALID_RESPONSE_STATUS */ public final class AAIResponseFilterPriority { - - private AAIResponseFilterPriority() {} - public static final int INVALID_RESPONSE_STATUS = 1000; + private AAIResponseFilterPriority() { + } - public static final int RESPONSE_TRANS_LOGGING = 3000; + public static final int INVALID_RESPONSE_STATUS = 1000; - public static final int HEADER_MANIPULATION = 4000; + public static final int RESPONSE_TRANS_LOGGING = 3000; + + public static final int HEADER_MANIPULATION = 4000; } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/post/InvalidResponseStatus.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/post/InvalidResponseStatus.java index 7fd0b9c..b28f0dd 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/post/InvalidResponseStatus.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/post/InvalidResponseStatus.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,47 +19,48 @@ */ package org.onap.aai.interceptors.post; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.logging.ErrorLogHelper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.core.MediaType; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.logging.ErrorLogHelper; @Priority(AAIResponseFilterPriority.INVALID_RESPONSE_STATUS) public class InvalidResponseStatus extends AAIContainerFilter implements ContainerResponseFilter { - @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { + @Override + public void filter(ContainerRequestContext requestContext, + ContainerResponseContext responseContext) throws IOException { - if(responseContext.getStatus() == 405){ + if (responseContext.getStatus() == 405) { - responseContext.setStatus(400); - AAIException e = new AAIException("AAI_3012"); - ArrayList<String> templateVars = new ArrayList<>(); + responseContext.setStatus(400); + AAIException e = new AAIException("AAI_3012"); + ArrayList<String> templateVars = new ArrayList<>(); - List<MediaType> mediaTypeList = new ArrayList<>(); + List<MediaType> mediaTypeList = new ArrayList<>(); - String contentType = responseContext.getHeaderString("Content-Type"); + String contentType = responseContext.getHeaderString("Content-Type"); - if (contentType == null) { - mediaTypeList.add(MediaType.APPLICATION_XML_TYPE); - } else { - mediaTypeList.add(MediaType.valueOf(contentType)); - } + if (contentType == null) { + mediaTypeList.add(MediaType.APPLICATION_XML_TYPE); + } else { + mediaTypeList.add(MediaType.valueOf(contentType)); + } - String message = ErrorLogHelper.getRESTAPIErrorResponse(mediaTypeList, e, templateVars); + String message = ErrorLogHelper.getRESTAPIErrorResponse(mediaTypeList, e, templateVars); - responseContext.setEntity(message); - } + responseContext.setEntity(message); + } - } + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/post/ResponseHeaderManipulation.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/post/ResponseHeaderManipulation.java index 9d4efe7..d13b122 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/post/ResponseHeaderManipulation.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/post/ResponseHeaderManipulation.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,46 +19,49 @@ */ package org.onap.aai.interceptors.post; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.interceptors.AAIHeaderProperties; +import java.io.IOException; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.core.MediaType; -import java.io.IOException; + +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.interceptors.AAIHeaderProperties; @Priority(AAIResponseFilterPriority.HEADER_MANIPULATION) -public class ResponseHeaderManipulation extends AAIContainerFilter implements ContainerResponseFilter { +public class ResponseHeaderManipulation extends AAIContainerFilter + implements ContainerResponseFilter { - private static final String DEFAULT_XML_TYPE = MediaType.APPLICATION_XML; + private static final String DEFAULT_XML_TYPE = MediaType.APPLICATION_XML; - @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { + @Override + public void filter(ContainerRequestContext requestContext, + ContainerResponseContext responseContext) throws IOException { - updateResponseHeaders(requestContext, responseContext); + updateResponseHeaders(requestContext, responseContext); - } + } - private void updateResponseHeaders(ContainerRequestContext requestContext, - ContainerResponseContext responseContext) { + private void updateResponseHeaders(ContainerRequestContext requestContext, + ContainerResponseContext responseContext) { - responseContext.getHeaders().add(AAIHeaderProperties.AAI_TX_ID, requestContext.getProperty(AAIHeaderProperties.AAI_TX_ID)); + responseContext.getHeaders().add(AAIHeaderProperties.AAI_TX_ID, + requestContext.getProperty(AAIHeaderProperties.AAI_TX_ID)); - String responseContentType = responseContext.getHeaderString("Content-Type"); + String responseContentType = responseContext.getHeaderString("Content-Type"); - if(responseContentType == null){ - String acceptType = requestContext.getHeaderString("Accept"); + if (responseContentType == null) { + String acceptType = requestContext.getHeaderString("Accept"); - if(acceptType == null || "*/*".equals(acceptType)){ - responseContext.getHeaders().putSingle("Content-Type", DEFAULT_XML_TYPE); - } else { - responseContext.getHeaders().putSingle("Content-Type", acceptType); - } - } + if (acceptType == null || "*/*".equals(acceptType)) { + responseContext.getHeaders().putSingle("Content-Type", DEFAULT_XML_TYPE); + } else { + responseContext.getHeaders().putSingle("Content-Type", acceptType); + } + } - } + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java index 51fe871..854eeed 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/post/ResponseTransactionLogging.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,6 +20,17 @@ package org.onap.aai.interceptors.post; import com.google.gson.JsonObject; + +import java.io.IOException; +import java.util.*; + +import javax.annotation.Priority; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.PathSegment; + import org.onap.aai.exceptions.AAIException; import org.onap.aai.interceptors.AAIContainerFilter; import org.onap.aai.interceptors.AAIHeaderProperties; @@ -29,133 +40,127 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import javax.annotation.Priority; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; -import javax.ws.rs.core.PathSegment; -import java.io.IOException; -import java.util.*; - @Priority(AAIResponseFilterPriority.RESPONSE_TRANS_LOGGING) -public class ResponseTransactionLogging extends AAIContainerFilter implements ContainerResponseFilter { - - private static final Logger TRANSACTION_LOGGER = LoggerFactory.getLogger(ResponseTransactionLogging.class); - - private final static String QUERY_API_PATH_SEGMENT = "query"; - private final static String NODES_QUERY_API_PATH_SEGMENT = "nodes-query"; - private final static String GENERIC_QUERY_API_PATH_SEGMENT = "generic-query"; - private final static String DSL_API_PATH_SEGMENT = "dsl"; - private final static String RECENTS_API_PATH_SEGMENT = "recents"; - private final static Set<String> READ_ONLY_QUERIES = getReadOnlyQueries(); - - @Autowired - private HttpServletResponse httpServletResponse; - - @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { - - this.transLogging(requestContext, responseContext); - - } - - private void transLogging(ContainerRequestContext requestContext, ContainerResponseContext responseContext) { - - String logValue; - String isGetTransactionResponseLoggingEnabled; - String postValue; - - try { - - logValue = AAIConfig.get("aai.transaction.logging"); - isGetTransactionResponseLoggingEnabled = AAIConfig.get("aai.transaction.logging.get"); - postValue = AAIConfig.get("aai.transaction.logging.post"); - } catch (AAIException e) { - return; - } - - String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID); - String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); - String fullUri = requestContext.getUriInfo().getRequestUri().toString(); - String requestTs = (String)requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST_TS); - - String httpMethod = requestContext.getMethod(); - - String status = Integer.toString(responseContext.getStatus()); - - String request = (String)requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST); - String response = this.getResponseString(responseContext); - - if (!Boolean.parseBoolean(logValue)) { - } else if (!Boolean.parseBoolean(postValue) && "POST".equals(httpMethod)) { - } else { - - JsonObject logEntry = new JsonObject(); - logEntry.addProperty("transactionId", transId); - logEntry.addProperty("status", status); - logEntry.addProperty("rqstDate", requestTs); - logEntry.addProperty("respDate", this.genDate()); - logEntry.addProperty("sourceId", fromAppId + ":" + transId); - logEntry.addProperty("resourceId", fullUri); - logEntry.addProperty("resourceType", httpMethod); - logEntry.addProperty("rqstBuf", Objects.toString(request, "")); - - boolean recordResponse = true; - if (!Boolean.parseBoolean(isGetTransactionResponseLoggingEnabled) && "GET".equals(httpMethod)) { - recordResponse = false; - } - else { - /** - * Parse the uri path and see if it is a read-only query - * If it is, do not record the response in the logs - */ - - List<PathSegment> pathSegmentList = requestContext.getUriInfo().getPathSegments(); - for (PathSegment queryType : pathSegmentList) { - if (READ_ONLY_QUERIES.contains(queryType.toString())) { - recordResponse = false; - } - } - - if (recordResponse) { - logEntry.addProperty("respBuf", Objects.toString(response, "")); - } - - try { - TRANSACTION_LOGGER.debug(logEntry.toString()); - } catch (Exception e) { - ErrorLogHelper.logError("AAI_4000", "Exception writing transaction log."); - } - } - } - - } - - private String getResponseString(ContainerResponseContext responseContext) { - JsonObject response = new JsonObject(); - response.addProperty("ID", responseContext.getHeaderString(AAIHeaderProperties.AAI_TX_ID)); - response.addProperty("Content-Type", this.httpServletResponse.getContentType()); - response.addProperty("Response-Code", responseContext.getStatus()); - response.addProperty("Headers", responseContext.getHeaders().toString()); - Optional<Object> entityOptional = Optional.ofNullable(responseContext.getEntity()); - if(entityOptional.isPresent()){ - response.addProperty("Entity", entityOptional.get().toString()); - } else { - response.addProperty("Entity", ""); - } - return response.toString(); - } - - private static Set<String> getReadOnlyQueries() { - Set<String> readOnlyQueries = new HashSet<String>(); - readOnlyQueries.add(NODES_QUERY_API_PATH_SEGMENT); - readOnlyQueries.add(GENERIC_QUERY_API_PATH_SEGMENT); - readOnlyQueries.add(RECENTS_API_PATH_SEGMENT); - readOnlyQueries.add(QUERY_API_PATH_SEGMENT); - readOnlyQueries.add(DSL_API_PATH_SEGMENT); - return readOnlyQueries; - } +public class ResponseTransactionLogging extends AAIContainerFilter + implements ContainerResponseFilter { + + private static final Logger TRANSACTION_LOGGER = + LoggerFactory.getLogger(ResponseTransactionLogging.class); + + private final static String QUERY_API_PATH_SEGMENT = "query"; + private final static String NODES_QUERY_API_PATH_SEGMENT = "nodes-query"; + private final static String GENERIC_QUERY_API_PATH_SEGMENT = "generic-query"; + private final static String DSL_API_PATH_SEGMENT = "dsl"; + private final static String RECENTS_API_PATH_SEGMENT = "recents"; + private final static Set<String> READ_ONLY_QUERIES = getReadOnlyQueries(); + + @Autowired + private HttpServletResponse httpServletResponse; + + @Override + public void filter(ContainerRequestContext requestContext, + ContainerResponseContext responseContext) throws IOException { + + this.transLogging(requestContext, responseContext); + + } + + private void transLogging(ContainerRequestContext requestContext, + ContainerResponseContext responseContext) { + + String logValue; + String isGetTransactionResponseLoggingEnabled; + String postValue; + + try { + + logValue = AAIConfig.get("aai.transaction.logging"); + isGetTransactionResponseLoggingEnabled = AAIConfig.get("aai.transaction.logging.get"); + postValue = AAIConfig.get("aai.transaction.logging.post"); + } catch (AAIException e) { + return; + } + + String transId = requestContext.getHeaderString(AAIHeaderProperties.TRANSACTION_ID); + String fromAppId = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); + String fullUri = requestContext.getUriInfo().getRequestUri().toString(); + String requestTs = (String) requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST_TS); + + String httpMethod = requestContext.getMethod(); + + String status = Integer.toString(responseContext.getStatus()); + + String request = (String) requestContext.getProperty(AAIHeaderProperties.AAI_REQUEST); + String response = this.getResponseString(responseContext); + + if (!Boolean.parseBoolean(logValue)) { + } else if (!Boolean.parseBoolean(postValue) && "POST".equals(httpMethod)) { + } else { + + JsonObject logEntry = new JsonObject(); + logEntry.addProperty("transactionId", transId); + logEntry.addProperty("status", status); + logEntry.addProperty("rqstDate", requestTs); + logEntry.addProperty("respDate", this.genDate()); + logEntry.addProperty("sourceId", fromAppId + ":" + transId); + logEntry.addProperty("resourceId", fullUri); + logEntry.addProperty("resourceType", httpMethod); + logEntry.addProperty("rqstBuf", Objects.toString(request, "")); + + boolean recordResponse = true; + if (!Boolean.parseBoolean(isGetTransactionResponseLoggingEnabled) + && "GET".equals(httpMethod)) { + recordResponse = false; + } else { + /** + * Parse the uri path and see if it is a read-only query + * If it is, do not record the response in the logs + */ + + List<PathSegment> pathSegmentList = requestContext.getUriInfo().getPathSegments(); + for (PathSegment queryType : pathSegmentList) { + if (READ_ONLY_QUERIES.contains(queryType.toString())) { + recordResponse = false; + } + } + + if (recordResponse) { + logEntry.addProperty("respBuf", Objects.toString(response, "")); + } + + try { + TRANSACTION_LOGGER.debug(logEntry.toString()); + } catch (Exception e) { + ErrorLogHelper.logError("AAI_4000", "Exception writing transaction log."); + } + } + } + + } + + private String getResponseString(ContainerResponseContext responseContext) { + JsonObject response = new JsonObject(); + response.addProperty("ID", responseContext.getHeaderString(AAIHeaderProperties.AAI_TX_ID)); + response.addProperty("Content-Type", this.httpServletResponse.getContentType()); + response.addProperty("Response-Code", responseContext.getStatus()); + response.addProperty("Headers", responseContext.getHeaders().toString()); + Optional<Object> entityOptional = Optional.ofNullable(responseContext.getEntity()); + if (entityOptional.isPresent()) { + response.addProperty("Entity", entityOptional.get().toString()); + } else { + response.addProperty("Entity", ""); + } + return response.toString(); + } + + private static Set<String> getReadOnlyQueries() { + Set<String> readOnlyQueries = new HashSet<String>(); + readOnlyQueries.add(NODES_QUERY_API_PATH_SEGMENT); + readOnlyQueries.add(GENERIC_QUERY_API_PATH_SEGMENT); + readOnlyQueries.add(RECENTS_API_PATH_SEGMENT); + readOnlyQueries.add(QUERY_API_PATH_SEGMENT); + readOnlyQueries.add(DSL_API_PATH_SEGMENT); + return readOnlyQueries; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java index 4af96c5..ee6374c 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/AAIRequestFilterPriority.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,25 +20,26 @@ package org.onap.aai.interceptors.pre; public final class AAIRequestFilterPriority { - - private AAIRequestFilterPriority() {} - - public static final int REQUEST_TRANS_LOGGING = 1000; - - public static final int HEADER_VALIDATION = 2000; - public static final int HTTP_HEADER = 4000; + private AAIRequestFilterPriority() { + } - public static final int LATEST = 4250; + public static final int REQUEST_TRANS_LOGGING = 1000; - public static final int AUTHORIZATION = 4500; + public static final int HEADER_VALIDATION = 2000; - public static final int RETIRED_SERVICE = 5000; + public static final int HTTP_HEADER = 4000; - public static final int VERSION = 5500; + public static final int LATEST = 4250; - public static final int HEADER_MANIPULATION = 6000; + public static final int AUTHORIZATION = 4500; - public static final int REQUEST_MODIFICATION = 7000; + public static final int RETIRED_SERVICE = 5000; + + public static final int VERSION = 5500; + + public static final int HEADER_MANIPULATION = 6000; + + public static final int REQUEST_MODIFICATION = 7000; } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java index d70cb01..ed13863 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/HeaderValidation.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,12 +19,10 @@ */ package org.onap.aai.interceptors.pre; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.interceptors.AAIHeaderProperties; -import org.onap.aai.logging.ErrorLogHelper; -import org.onap.logging.filter.base.Constants; -import org.onap.logging.ref.slf4j.ONAPLogConstants; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; @@ -32,95 +30,102 @@ import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.interceptors.AAIHeaderProperties; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.logging.filter.base.Constants; +import org.onap.logging.ref.slf4j.ONAPLogConstants; @PreMatching @Priority(AAIRequestFilterPriority.HEADER_VALIDATION) public class HeaderValidation extends AAIContainerFilter implements ContainerRequestFilter { - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + Optional<Response> oResp; + + List<MediaType> acceptHeaderValues = requestContext.getAcceptableMediaTypes(); - Optional<Response> oResp; + String fromAppId = getPartnerName(requestContext); + oResp = this.validateHeaderValuePresence(fromAppId, "AAI_4009", acceptHeaderValues); + if (oResp.isPresent()) { + requestContext.abortWith(oResp.get()); + return; + } + String transId = getRequestId(requestContext); + oResp = this.validateHeaderValuePresence(transId, "AAI_4010", acceptHeaderValues); + if (oResp.isPresent()) { + requestContext.abortWith(oResp.get()); + return; + } + } - List<MediaType> acceptHeaderValues = requestContext.getAcceptableMediaTypes(); + private Optional<Response> validateHeaderValuePresence(String value, String errorCode, + List<MediaType> acceptHeaderValues) { + Response response = null; + AAIException aaie; + if (value == null || value.isEmpty()) { + aaie = new AAIException(errorCode); + return Optional + .of(Response + .status(aaie.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())) + .build()); + } - String fromAppId = getPartnerName(requestContext); - oResp = this.validateHeaderValuePresence(fromAppId, "AAI_4009", acceptHeaderValues); - if (oResp.isPresent()) { - requestContext.abortWith(oResp.get()); - return; - } - String transId = getRequestId(requestContext); - oResp = this.validateHeaderValuePresence(transId, "AAI_4010", acceptHeaderValues); - if (oResp.isPresent()) { - requestContext.abortWith(oResp.get()); - return; - } - } - - private Optional<Response> validateHeaderValuePresence(String value, String errorCode, - List<MediaType> acceptHeaderValues) { - Response response = null; - AAIException aaie; - if (value == null || value.isEmpty()) { - aaie = new AAIException(errorCode); - return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())) - .build()); - } + return Optional.ofNullable(response); + } - return Optional.ofNullable(response); - } - public String getRequestId(ContainerRequestContext requestContext) { - String requestId = requestContext.getHeaderString(ONAPLogConstants.Headers.REQUEST_ID); - if (requestId == null || requestId.isEmpty()) { - requestId = requestContext.getHeaderString(Constants.HttpHeaders.HEADER_REQUEST_ID); - if (requestId == null || requestId.isEmpty()) { - requestId = requestContext.getHeaderString(Constants.HttpHeaders.TRANSACTION_ID); - if (requestId == null || requestId.isEmpty()) { - requestId = requestContext.getHeaderString(Constants.HttpHeaders.ECOMP_REQUEST_ID); - if (requestId == null || requestId.isEmpty()) { - return requestId; - } - } - } - } - if (requestContext.getHeaders().get(ONAPLogConstants.Headers.REQUEST_ID) != null) { - requestContext.getHeaders().get(ONAPLogConstants.Headers.REQUEST_ID).clear(); - } - if (requestContext.getHeaders().get(Constants.HttpHeaders.TRANSACTION_ID) != null) { - requestContext.getHeaders().get(Constants.HttpHeaders.TRANSACTION_ID).clear(); - } - if (requestContext.getHeaders().get(Constants.HttpHeaders.HEADER_REQUEST_ID) != null) { - requestContext.getHeaders().get(Constants.HttpHeaders.HEADER_REQUEST_ID).clear(); - } - if (requestContext.getHeaders().get(Constants.HttpHeaders.ECOMP_REQUEST_ID) != null) { - requestContext.getHeaders().get(Constants.HttpHeaders.ECOMP_REQUEST_ID).clear(); - } - requestContext.getHeaders().add(Constants.HttpHeaders.TRANSACTION_ID, requestId); + public String getRequestId(ContainerRequestContext requestContext) { + String requestId = requestContext.getHeaderString(ONAPLogConstants.Headers.REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + requestId = requestContext.getHeaderString(Constants.HttpHeaders.HEADER_REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + requestId = requestContext.getHeaderString(Constants.HttpHeaders.TRANSACTION_ID); + if (requestId == null || requestId.isEmpty()) { + requestId = + requestContext.getHeaderString(Constants.HttpHeaders.ECOMP_REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + return requestId; + } + } + } + } + if (requestContext.getHeaders().get(ONAPLogConstants.Headers.REQUEST_ID) != null) { + requestContext.getHeaders().get(ONAPLogConstants.Headers.REQUEST_ID).clear(); + } + if (requestContext.getHeaders().get(Constants.HttpHeaders.TRANSACTION_ID) != null) { + requestContext.getHeaders().get(Constants.HttpHeaders.TRANSACTION_ID).clear(); + } + if (requestContext.getHeaders().get(Constants.HttpHeaders.HEADER_REQUEST_ID) != null) { + requestContext.getHeaders().get(Constants.HttpHeaders.HEADER_REQUEST_ID).clear(); + } + if (requestContext.getHeaders().get(Constants.HttpHeaders.ECOMP_REQUEST_ID) != null) { + requestContext.getHeaders().get(Constants.HttpHeaders.ECOMP_REQUEST_ID).clear(); + } + requestContext.getHeaders().add(Constants.HttpHeaders.TRANSACTION_ID, requestId); - return requestId; - } + return requestId; + } - public String getPartnerName(ContainerRequestContext requestContext) { - String partnerName = requestContext.getHeaderString(ONAPLogConstants.Headers.PARTNER_NAME); - if (partnerName == null || (partnerName.isEmpty())) { - partnerName = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); - if (partnerName == null || (partnerName.isEmpty())) { - return partnerName; - } - } - if (requestContext.getHeaders().get(ONAPLogConstants.Headers.PARTNER_NAME) != null) { - requestContext.getHeaders().get(ONAPLogConstants.Headers.PARTNER_NAME).clear(); - } - if (requestContext.getHeaders().get(AAIHeaderProperties.FROM_APP_ID) != null) { - requestContext.getHeaders().get(AAIHeaderProperties.FROM_APP_ID).clear(); - } - requestContext.getHeaders().add(AAIHeaderProperties.FROM_APP_ID, partnerName); - return partnerName; - } + public String getPartnerName(ContainerRequestContext requestContext) { + String partnerName = requestContext.getHeaderString(ONAPLogConstants.Headers.PARTNER_NAME); + if (partnerName == null || (partnerName.isEmpty())) { + partnerName = requestContext.getHeaderString(AAIHeaderProperties.FROM_APP_ID); + if (partnerName == null || (partnerName.isEmpty())) { + return partnerName; + } + } + if (requestContext.getHeaders().get(ONAPLogConstants.Headers.PARTNER_NAME) != null) { + requestContext.getHeaders().get(ONAPLogConstants.Headers.PARTNER_NAME).clear(); + } + if (requestContext.getHeaders().get(AAIHeaderProperties.FROM_APP_ID) != null) { + requestContext.getHeaders().get(AAIHeaderProperties.FROM_APP_ID).clear(); + } + requestContext.getHeaders().add(AAIHeaderProperties.FROM_APP_ID, partnerName); + return partnerName; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/HttpHeaderInterceptor.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/HttpHeaderInterceptor.java index ee04453..5d9c1ff 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/HttpHeaderInterceptor.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/HttpHeaderInterceptor.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,15 +19,16 @@ */ package org.onap.aai.interceptors.pre; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.interceptors.AAIHeaderProperties; +import java.io.IOException; import javax.annotation.Priority; import javax.ws.rs.HttpMethod; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; -import java.io.IOException; + +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.interceptors.AAIHeaderProperties; /** * The Class HttpHeaderInterceptor @@ -35,16 +36,18 @@ import java.io.IOException; @PreMatching @Priority(AAIRequestFilterPriority.HTTP_HEADER) public class HttpHeaderInterceptor extends AAIContainerFilter implements ContainerRequestFilter { - public static final String patchMethod = "PATCH"; - + public static final String patchMethod = "PATCH"; + @Override public void filter(ContainerRequestContext containerRequestContext) throws IOException { - String overrideMethod = containerRequestContext.getHeaderString(AAIHeaderProperties.HTTP_METHOD_OVERRIDE); - String httpMethod = containerRequestContext.getMethod(); - - if (HttpMethod.POST.equalsIgnoreCase(httpMethod) && patchMethod.equalsIgnoreCase(overrideMethod)) { - containerRequestContext.setMethod(patchMethod); - } + String overrideMethod = + containerRequestContext.getHeaderString(AAIHeaderProperties.HTTP_METHOD_OVERRIDE); + String httpMethod = containerRequestContext.getMethod(); + + if (HttpMethod.POST.equalsIgnoreCase(httpMethod) + && patchMethod.equalsIgnoreCase(overrideMethod)) { + containerRequestContext.setMethod(patchMethod); + } } - + } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java index a6c5ed9..78ab1a9 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/OneWaySslAuthorization.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,13 +19,10 @@ */ package org.onap.aai.interceptors.pre; -import org.onap.aai.Profiles; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.service.AuthorizationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Profile; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; @@ -33,10 +30,14 @@ import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; + +import org.onap.aai.Profiles; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.service.AuthorizationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; @Profile(Profiles.ONE_WAY_SSL) @PreMatching @@ -47,17 +48,17 @@ public class OneWaySslAuthorization extends AAIContainerFilter implements Contai private AuthorizationService authorizationService; @Override - public void filter(ContainerRequestContext containerRequestContext) throws IOException - { + public void filter(ContainerRequestContext containerRequestContext) throws IOException { - if(containerRequestContext.getUriInfo().getRequestUri().getPath().matches("^.*/util/echo$")){ + if (containerRequestContext.getUriInfo().getRequestUri().getPath() + .matches("^.*/util/echo$")) { return; } String basicAuth = containerRequestContext.getHeaderString("Authorization"); List<MediaType> acceptHeaderValues = containerRequestContext.getAcceptableMediaTypes(); - if(basicAuth == null || !basicAuth.startsWith("Basic ")){ + if (basicAuth == null || !basicAuth.startsWith("Basic ")) { Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues); containerRequestContext.abortWith(responseOptional.get()); return; @@ -65,7 +66,7 @@ public class OneWaySslAuthorization extends AAIContainerFilter implements Contai basicAuth = basicAuth.replaceAll("Basic ", ""); - if(!authorizationService.checkIfUserAuthorized(basicAuth)){ + if (!authorizationService.checkIfUserAuthorized(basicAuth)) { Optional<Response> responseOptional = errorResponse("AAI_3300", acceptHeaderValues); containerRequestContext.abortWith(responseOptional.get()); return; @@ -76,8 +77,9 @@ public class OneWaySslAuthorization extends AAIContainerFilter implements Contai private Optional<Response> errorResponse(String errorCode, List<MediaType> acceptHeaderValues) { AAIException aaie = new AAIException(errorCode); return Optional.of(Response.status(aaie.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())) - .build()); + .entity( + ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaderValues, aaie, new ArrayList<>())) + .build()); } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java index d2dcc0b..4946e7d 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestHeaderManipulation.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,42 +19,44 @@ */ package org.onap.aai.interceptors.pre; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.interceptors.AAIHeaderProperties; +import java.util.Collections; +import java.util.regex.Matcher; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.MultivaluedMap; -import java.util.Collections; -import java.util.regex.Matcher; + +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.interceptors.AAIHeaderProperties; @PreMatching @Priority(AAIRequestFilterPriority.HEADER_MANIPULATION) -public class RequestHeaderManipulation extends AAIContainerFilter implements ContainerRequestFilter { +public class RequestHeaderManipulation extends AAIContainerFilter + implements ContainerRequestFilter { - @Override - public void filter(ContainerRequestContext requestContext) { + @Override + public void filter(ContainerRequestContext requestContext) { - String uri = requestContext.getUriInfo().getPath(); - this.addRequestContext(uri, requestContext.getHeaders()); + String uri = requestContext.getUriInfo().getPath(); + this.addRequestContext(uri, requestContext.getHeaders()); - } - - private void addRequestContext(String uri, MultivaluedMap<String, String> requestHeaders) { + } - String rc = ""; + private void addRequestContext(String uri, MultivaluedMap<String, String> requestHeaders) { + + String rc = ""; Matcher match = VersionInterceptor.EXTRACT_VERSION_PATTERN.matcher(uri); if (match.find()) { rc = match.group(1); } - if (requestHeaders.containsKey(AAIHeaderProperties.REQUEST_CONTEXT)) { - requestHeaders.remove(AAIHeaderProperties.REQUEST_CONTEXT); - } - requestHeaders.put(AAIHeaderProperties.REQUEST_CONTEXT, Collections.singletonList(rc)); - } + if (requestHeaders.containsKey(AAIHeaderProperties.REQUEST_CONTEXT)) { + requestHeaders.remove(AAIHeaderProperties.REQUEST_CONTEXT); + } + requestHeaders.put(AAIHeaderProperties.REQUEST_CONTEXT, Collections.singletonList(rc)); + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestModification.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestModification.java index acd1305..f7d863d 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestModification.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestModification.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,7 +19,12 @@ */ package org.onap.aai.interceptors.pre; -import org.onap.aai.interceptors.AAIContainerFilter; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; @@ -27,49 +32,45 @@ import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriBuilder; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; + +import org.onap.aai.interceptors.AAIContainerFilter; @PreMatching @Priority(AAIRequestFilterPriority.REQUEST_MODIFICATION) public class RequestModification extends AAIContainerFilter implements ContainerRequestFilter { - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + this.cleanDME2QueryParams(requestContext); - this.cleanDME2QueryParams(requestContext); + } - } - - private void cleanDME2QueryParams(ContainerRequestContext request) { - UriBuilder builder = request.getUriInfo().getRequestUriBuilder(); - MultivaluedMap<String, String> queries = request.getUriInfo().getQueryParameters(); + private void cleanDME2QueryParams(ContainerRequestContext request) { + UriBuilder builder = request.getUriInfo().getRequestUriBuilder(); + MultivaluedMap<String, String> queries = request.getUriInfo().getQueryParameters(); - String[] blacklist = { "version", "envContext", "routeOffer" }; - Set<String> blacklistSet = Arrays.stream(blacklist).collect(Collectors.toSet()); + String[] blacklist = {"version", "envContext", "routeOffer"}; + Set<String> blacklistSet = Arrays.stream(blacklist).collect(Collectors.toSet()); - boolean remove = true; + boolean remove = true; - for (String param : blacklistSet) { - if (!queries.containsKey(param)) { - remove = false; - break; - } - } + for (String param : blacklistSet) { + if (!queries.containsKey(param)) { + remove = false; + break; + } + } - if (remove) { - for (Map.Entry<String, List<String>> query : queries.entrySet()) { - String key = query.getKey(); - if (blacklistSet.contains(key)) { - builder.replaceQueryParam(key); - } - } - } - request.setRequestUri(builder.build()); - } + if (remove) { + for (Map.Entry<String, List<String>> query : queries.entrySet()) { + String key = query.getKey(); + if (blacklistSet.contains(key)) { + builder.replaceQueryParam(key); + } + } + } + request.setRequestUri(builder.build()); + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java index 03cac8d..b37a804 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RequestTransactionLogging.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,6 +20,24 @@ package org.onap.aai.interceptors.pre; import com.google.gson.JsonObject; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.SecureRandom; +import java.util.Random; +import java.util.UUID; + +import javax.annotation.Priority; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; + import org.glassfish.jersey.message.internal.ReaderWriter; import org.glassfish.jersey.server.ContainerException; import org.onap.aai.exceptions.AAIException; @@ -31,113 +49,104 @@ import org.onap.aai.util.HbaseSaltPrefixer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; -import javax.annotation.Priority; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.PreMatching; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.UriInfo; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.SecureRandom; -import java.util.Random; -import java.util.UUID; - @PreMatching @Priority(AAIRequestFilterPriority.REQUEST_TRANS_LOGGING) -public class RequestTransactionLogging extends AAIContainerFilter implements ContainerRequestFilter { - - @Autowired - private HttpServletRequest httpServletRequest; - - private static final String DEFAULT_CONTENT_TYPE = MediaType.APPLICATION_JSON; - private static final String DEFAULT_RESPONSE_TYPE = MediaType.APPLICATION_XML; - - private static final String CONTENT_TYPE = "Content-Type"; - private static final String ACCEPT = "Accept"; - private static final String TEXT_PLAIN = "text/plain"; - private static final String WILDCARD = "*/*"; - private static final String APPLICATION_JSON = "application/json"; - - @Override - public void filter(ContainerRequestContext requestContext) throws IOException { - - String currentTimeStamp = genDate(); - String fullId = this.getAAITxIdToHeader(currentTimeStamp); - this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_TX_ID, fullId); - this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST, this.getRequest(requestContext, fullId)); - this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST_TS, currentTimeStamp); - this.addDefaultContentType(requestContext); - } - - private void addToRequestContext(ContainerRequestContext requestContext, String name, String aaiTxIdToHeader) { - requestContext.setProperty(name, aaiTxIdToHeader); - } - - private void addDefaultContentType(ContainerRequestContext requestContext) { - - String contentType = requestContext.getHeaderString(CONTENT_TYPE); - String acceptType = requestContext.getHeaderString(ACCEPT); - - if(contentType == null || contentType.contains(TEXT_PLAIN)){ - requestContext.getHeaders().putSingle(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); - } - - if(WILDCARD.equals(acceptType) || StringUtils.isEmpty(acceptType) || acceptType.contains(TEXT_PLAIN)){ - UriInfo uriInfo = requestContext.getUriInfo(); - if(uriInfo != null){ - String path = uriInfo.getPath(); - if(path.endsWith("/dsl") || path.endsWith("/query") || path.contains("/recents/")){ - requestContext.getHeaders().putSingle(ACCEPT, APPLICATION_JSON); - } else { - requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE); - } - } else { - requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE); - } - } - } - - private String getAAITxIdToHeader(String currentTimeStamp) { - String txId = UUID.randomUUID().toString(); - try { - Random rand = new SecureRandom(); - int number = rand.nextInt(99999); - txId = HbaseSaltPrefixer.getInstance().prependSalt(AAIConfig.get(AAIConstants.AAI_NODENAME) + "-" - + currentTimeStamp + "-" + number ); //new Random(System.currentTimeMillis()).nextInt(99999) - } catch (AAIException e) { - } - - return txId; - } - - private String getRequest(ContainerRequestContext requestContext, String fullId) { - - JsonObject request = new JsonObject(); - request.addProperty("ID", fullId); - request.addProperty("Http-Method", requestContext.getMethod()); - request.addProperty(CONTENT_TYPE, httpServletRequest.getContentType()); - request.addProperty("Headers", requestContext.getHeaders().toString()); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - InputStream in = requestContext.getEntityStream(); - - try { - if (in.available() > 0) { - ReaderWriter.writeTo(in, out); - byte[] requestEntity = out.toByteArray(); - request.addProperty("Payload", new String(requestEntity, "UTF-8")); - requestContext.setEntityStream(new ByteArrayInputStream(requestEntity)); - } - } catch (IOException ex) { - throw new ContainerException(ex); - } - - return request.toString(); - } +public class RequestTransactionLogging extends AAIContainerFilter + implements ContainerRequestFilter { + + @Autowired + private HttpServletRequest httpServletRequest; + + private static final String DEFAULT_CONTENT_TYPE = MediaType.APPLICATION_JSON; + private static final String DEFAULT_RESPONSE_TYPE = MediaType.APPLICATION_XML; + + private static final String CONTENT_TYPE = "Content-Type"; + private static final String ACCEPT = "Accept"; + private static final String TEXT_PLAIN = "text/plain"; + private static final String WILDCARD = "*/*"; + private static final String APPLICATION_JSON = "application/json"; + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + String currentTimeStamp = genDate(); + String fullId = this.getAAITxIdToHeader(currentTimeStamp); + this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_TX_ID, fullId); + this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST, + this.getRequest(requestContext, fullId)); + this.addToRequestContext(requestContext, AAIHeaderProperties.AAI_REQUEST_TS, + currentTimeStamp); + this.addDefaultContentType(requestContext); + } + + private void addToRequestContext(ContainerRequestContext requestContext, String name, + String aaiTxIdToHeader) { + requestContext.setProperty(name, aaiTxIdToHeader); + } + + private void addDefaultContentType(ContainerRequestContext requestContext) { + + String contentType = requestContext.getHeaderString(CONTENT_TYPE); + String acceptType = requestContext.getHeaderString(ACCEPT); + + if (contentType == null || contentType.contains(TEXT_PLAIN)) { + requestContext.getHeaders().putSingle(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); + } + + if (WILDCARD.equals(acceptType) || StringUtils.isEmpty(acceptType) + || acceptType.contains(TEXT_PLAIN)) { + UriInfo uriInfo = requestContext.getUriInfo(); + if (uriInfo != null) { + String path = uriInfo.getPath(); + if (path.endsWith("/dsl") || path.endsWith("/query") + || path.contains("/recents/")) { + requestContext.getHeaders().putSingle(ACCEPT, APPLICATION_JSON); + } else { + requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE); + } + } else { + requestContext.getHeaders().putSingle(ACCEPT, DEFAULT_RESPONSE_TYPE); + } + } + } + + private String getAAITxIdToHeader(String currentTimeStamp) { + String txId = UUID.randomUUID().toString(); + try { + Random rand = new SecureRandom(); + int number = rand.nextInt(99999); + txId = HbaseSaltPrefixer.getInstance().prependSalt( + AAIConfig.get(AAIConstants.AAI_NODENAME) + "-" + currentTimeStamp + "-" + number); // new + // Random(System.currentTimeMillis()).nextInt(99999) + } catch (AAIException e) { + } + + return txId; + } + + private String getRequest(ContainerRequestContext requestContext, String fullId) { + + JsonObject request = new JsonObject(); + request.addProperty("ID", fullId); + request.addProperty("Http-Method", requestContext.getMethod()); + request.addProperty(CONTENT_TYPE, httpServletRequest.getContentType()); + request.addProperty("Headers", requestContext.getHeaders().toString()); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputStream in = requestContext.getEntityStream(); + + try { + if (in.available() > 0) { + ReaderWriter.writeTo(in, out); + byte[] requestEntity = out.toByteArray(); + request.addProperty("Payload", new String(requestEntity, "UTF-8")); + requestContext.setEntityStream(new ByteArrayInputStream(requestEntity)); + } + } catch (IOException ex) { + throw new ContainerException(ex); + } + + return request.toString(); + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RetiredInterceptor.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RetiredInterceptor.java index 643793d..d1aa2e9 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RetiredInterceptor.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/RetiredInterceptor.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,6 +19,18 @@ */ package org.onap.aai.interceptors.pre; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.Priority; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.Response; + import org.onap.aai.exceptions.AAIException; import org.onap.aai.interceptors.AAIContainerFilter; import org.onap.aai.logging.ErrorLogHelper; @@ -27,17 +39,6 @@ import org.onap.aai.util.AAIConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import javax.annotation.Priority; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.PreMatching; -import javax.ws.rs.core.Response; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - // Can cache this so if the uri was already cached then it won't run the string // matching each time but only does it for the first time @@ -52,13 +53,15 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR private String basePath; @Autowired - public RetiredInterceptor(RetiredService retiredService, @Value("${schema.uri.base.path}") String basePath){ + public RetiredInterceptor(RetiredService retiredService, + @Value("${schema.uri.base.path}") String basePath) { this.retiredService = retiredService; this.basePath = basePath; - if(!basePath.endsWith("/")){ + if (!basePath.endsWith("/")) { this.basePath = basePath + "/"; } } + @Override public void filter(ContainerRequestContext containerRequestContext) throws IOException { @@ -68,8 +71,8 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR List<Pattern> retiredAllVersionList = retiredService.getRetiredAllVersionList(); - - if(checkIfUriRetired(containerRequestContext, retiredAllVersionList, version, requestURI, "")){ + if (checkIfUriRetired(containerRequestContext, retiredAllVersionList, version, requestURI, + "")) { return; } @@ -79,17 +82,13 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR } public boolean checkIfUriRetired(ContainerRequestContext containerRequestContext, - List<Pattern> retiredPatterns, - String version, - String requestURI, - String message){ - + List<Pattern> retiredPatterns, String version, String requestURI, String message) { - for(Pattern retiredPattern : retiredPatterns){ - if(retiredPattern.matcher(requestURI).matches()){ + for (Pattern retiredPattern : retiredPatterns) { + if (retiredPattern.matcher(requestURI).matches()) { AAIException e; - if(message == null){ + if (message == null) { e = new AAIException("AAI_3007"); } else { e = new AAIException("AAI_3015"); @@ -99,25 +98,20 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR if (templateVars.isEmpty()) { templateVars.add("PUT"); - if(requestURI != null){ + if (requestURI != null) { requestURI = requestURI.replaceAll(basePath, ""); } templateVars.add(requestURI); - if(message == null){ + if (message == null) { templateVars.add(version); templateVars.add(AAIConfig.get("aai.default.api.version", "")); } } - Response response = Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity( - ErrorLogHelper - .getRESTAPIErrorResponse( - containerRequestContext.getAcceptableMediaTypes(), e, templateVars - ) - ) - .build(); + Response response = Response.status(e.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponse( + containerRequestContext.getAcceptableMediaTypes(), e, templateVars)) + .build(); containerRequestContext.abortWith(response); @@ -129,17 +123,16 @@ public class RetiredInterceptor extends AAIContainerFilter implements ContainerR } public boolean checkIfUriRetired(ContainerRequestContext containerRequestContext, - List<Pattern> retiredPatterns, - String version, - String requestURI){ - return checkIfUriRetired(containerRequestContext, retiredPatterns, version, requestURI, null); + List<Pattern> retiredPatterns, String version, String requestURI) { + return checkIfUriRetired(containerRequestContext, retiredPatterns, version, requestURI, + null); } protected String extractVersionFromPath(String requestURI) { Matcher versionMatcher = VERSION_PATTERN.matcher(requestURI); String version = null; - if(versionMatcher.find()){ + if (versionMatcher.find()) { version = versionMatcher.group(0); } return version; 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 902d6f0..944d999 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,23 +19,24 @@ */ package org.onap.aai.interceptors.pre; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.logging.ErrorLogHelper; -import org.onap.aai.setup.SchemaVersion; -import org.onap.aai.setup.SchemaVersions; -import org.springframework.beans.factory.annotation.Autowired; +import java.util.ArrayList; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.Response; -import java.util.ArrayList; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.setup.SchemaVersion; +import org.onap.aai.setup.SchemaVersions; +import org.springframework.beans.factory.annotation.Autowired; @PreMatching @Priority(AAIRequestFilterPriority.VERSION) @@ -48,11 +49,9 @@ public class VersionInterceptor extends AAIContainerFilter implements ContainerR private final SchemaVersions schemaVersions; @Autowired - public VersionInterceptor(SchemaVersions schemaVersions){ + public VersionInterceptor(SchemaVersions schemaVersions) { this.schemaVersions = schemaVersions; - allowedVersions = schemaVersions.getVersions() - .stream() - .map(SchemaVersion::toString) + allowedVersions = schemaVersions.getVersions().stream().map(SchemaVersion::toString) .collect(Collectors.toSet()); } @@ -62,26 +61,31 @@ 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")|| uri.startsWith("cq2gremlin")|| uri.startsWith("cq2gremlintest")) { + if (uri.startsWith("search") || uri.startsWith("util/echo") || uri.startsWith("tools") + || uri.startsWith("recents") || uri.startsWith("cq2gremlin") + || uri.startsWith("cq2gremlintest")) { return; - } + } Matcher matcher = EXTRACT_VERSION_PATTERN.matcher(uri); String version = null; - if(matcher.matches()){ + if (matcher.matches()) { version = matcher.group(1); } else { - requestContext.abortWith(createInvalidVersionResponse("AAI_3017", requestContext, version)); + requestContext + .abortWith(createInvalidVersionResponse("AAI_3017", requestContext, version)); return; } - if(!allowedVersions.contains(version)){ - requestContext.abortWith(createInvalidVersionResponse("AAI_3016", requestContext, version)); + if (!allowedVersions.contains(version)) { + requestContext + .abortWith(createInvalidVersionResponse("AAI_3016", requestContext, version)); } } - private Response createInvalidVersionResponse(String errorCode, ContainerRequestContext context, String version) { + private Response createInvalidVersionResponse(String errorCode, ContainerRequestContext context, + String version) { AAIException e = new AAIException(errorCode); ArrayList<String> templateVars = new ArrayList<>(); @@ -91,11 +95,9 @@ public class VersionInterceptor extends AAIContainerFilter implements ContainerR templateVars.add(version); } - String entity = ErrorLogHelper.getRESTAPIErrorResponse(context.getAcceptableMediaTypes(), e, templateVars); + String entity = ErrorLogHelper.getRESTAPIErrorResponse(context.getAcceptableMediaTypes(), e, + templateVars); - return Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity(entity) - .build(); + return Response.status(e.getErrorObject().getHTTPResponseCode()).entity(entity).build(); } } diff --git a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/VersionLatestInterceptor.java b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/VersionLatestInterceptor.java index 124bc1a..22f923d 100644 --- a/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/VersionLatestInterceptor.java +++ b/aai-traversal/src/main/java/org/onap/aai/interceptors/pre/VersionLatestInterceptor.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,15 +19,16 @@ */ package org.onap.aai.interceptors.pre; -import org.onap.aai.interceptors.AAIContainerFilter; -import org.onap.aai.setup.SchemaVersions; -import org.springframework.beans.factory.annotation.Autowired; +import java.net.URI; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; -import java.net.URI; + +import org.onap.aai.interceptors.AAIContainerFilter; +import org.onap.aai.setup.SchemaVersions; +import org.springframework.beans.factory.annotation.Autowired; @PreMatching @Priority(AAIRequestFilterPriority.LATEST) @@ -36,7 +37,7 @@ public class VersionLatestInterceptor extends AAIContainerFilter implements Cont private final SchemaVersions schemaVersions; @Autowired - public VersionLatestInterceptor(SchemaVersions schemaVersions){ + public VersionLatestInterceptor(SchemaVersions schemaVersions) { this.schemaVersions = schemaVersions; } @@ -45,10 +46,12 @@ public class VersionLatestInterceptor extends AAIContainerFilter implements Cont String uri = requestContext.getUriInfo().getPath(); - if(uri.startsWith("latest")){ - String rawPath = requestContext.getUriInfo().getRequestUri().getRawPath(); - String updatedPath = rawPath.replaceFirst("latest",schemaVersions.getDefaultVersion().toString()); - URI latest = requestContext.getUriInfo().getRequestUriBuilder().replacePath(updatedPath).build(); + if (uri.startsWith("latest")) { + String rawPath = requestContext.getUriInfo().getRequestUri().getRawPath(); + String updatedPath = + rawPath.replaceFirst("latest", schemaVersions.getDefaultVersion().toString()); + URI latest = + requestContext.getUriInfo().getRequestUriBuilder().replacePath(updatedPath).build(); requestContext.setRequestUri(latest); 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 index d075f70..6e76c29 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,6 +19,16 @@ */ 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.*; + import org.onap.aai.config.SpringContextAware; import org.onap.aai.introspection.LoaderFactory; import org.onap.aai.rest.db.HttpEntry; @@ -34,83 +44,72 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.RequestBody; -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.*; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - - @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{ - 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); - traversalUriHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); - 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(); - } - - } + 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 { + 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); + traversalUriHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); + 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 index e3cfaca..626c5f3 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,9 +19,19 @@ */ package org.onap.aai.rest; - import com.beust.jcommander.internal.Lists; import com.beust.jcommander.internal.Maps; + +import java.util.*; +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.*; + 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; @@ -49,171 +59,156 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.RequestBody; -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.*; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - - @Path("/cq2gremlintest") public class CQ2GremlinTest extends RESTAPI { - private static final Logger LOGGER = LoggerFactory.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); - traversalUriHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); - 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("v19")); - LinkedHashMap <String, Object> params = new LinkedHashMap<>(); - - //Adding parameters - content.getQueryRequiredProperties().forEach(params::put); - content.getQueryOptionalProperties().forEach(params::put); - - 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().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(k); - 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().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().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(",")); - } - - + private static final Logger LOGGER = LoggerFactory.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); + traversalUriHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion()); + 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("v19")); + LinkedHashMap<String, Object> params = new LinkedHashMap<>(); + + // Adding parameters + content.getQueryRequiredProperties().forEach(params::put); + content.getQueryOptionalProperties().forEach(params::put); + + 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().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(k); + 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().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() + .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 fefd2dc..2b6bbb9 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -22,7 +22,17 @@ package org.onap.aai.rest; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; + import io.micrometer.core.annotation.Timed; + +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; + import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.janusgraph.core.SchemaViolationException; import org.onap.aai.concurrent.AaiCallable; @@ -51,222 +61,211 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; -import java.util.*; -import java.util.stream.Collectors; - @Path("{version: v[1-9][0-9]*|latest}/dsl") @Timed public class DslConsumer extends TraversalConsumer { - private HttpEntry traversalUriHttpEntry; - - private QueryProcessorType processorType = QueryProcessorType.LOCAL_GROOVY; - - private static final Logger LOGGER = LoggerFactory.getLogger(DslConsumer.class); - - private DslQueryProcessor dslQueryProcessor; - - private SchemaVersions schemaVersions; - - private String basePath; - - private GremlinServerSingleton gremlinServerSingleton; - private final QueryVersion DEFAULT_VERSION = QueryVersion.V1; - private QueryVersion dslApiVersion = DEFAULT_VERSION; - - private XmlFormatTransformer xmlFormatTransformer; - - @Autowired - public DslConsumer(HttpEntry traversalUriHttpEntry, DslQueryProcessor dslQueryProcessor, - SchemaVersions schemaVersions, GremlinServerSingleton gremlinServerSingleton, - XmlFormatTransformer xmlFormatTransformer, - @Value("${schema.uri.base.path}") String basePath) { - this.traversalUriHttpEntry = traversalUriHttpEntry; - this.dslQueryProcessor = dslQueryProcessor; - this.schemaVersions = schemaVersions; - this.gremlinServerSingleton = gremlinServerSingleton; - this.xmlFormatTransformer = xmlFormatTransformer; - this.basePath = basePath; - } - - @PUT - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response executeQuery(String content, - @PathParam("version") String versionParam, - @DefaultValue("graphson") @QueryParam("format") String queryFormat, - @DefaultValue("no_op") @QueryParam("subgraph") String subgraph, - @DefaultValue("all") @QueryParam("validate") String validate, - @Context HttpHeaders headers, - @Context HttpServletRequest req, - @Context UriInfo info, - @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, - @DefaultValue("-1") @QueryParam("resultSize") String resultSize) { - Set<String> roles = this.getRoles(req.getUserPrincipal()); - - 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() throws Exception { - return (processExecuteQuery(content, req, versionParam, queryFormat, subgraph, validate, headers, info, - resultIndex, resultSize, roles)); - } - } - ); - } - - public Response processExecuteQuery(String content, HttpServletRequest req, String versionParam, String queryFormat, String subgraph, - String validate, HttpHeaders headers, UriInfo info, String resultIndex, - String resultSize, Set<String> roles) { - - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String dslOverride = headers.getRequestHeaders().getFirst("X-DslOverride"); - - Optional<String> dslApiVersionHeader = Optional.ofNullable(headers.getRequestHeaders().getFirst("X-DslApiVersion")); - if (dslApiVersionHeader.isPresent()) { - try { - dslApiVersion = QueryVersion.valueOf(dslApiVersionHeader.get()); - } catch (IllegalArgumentException e) { - LOGGER.debug("Defaulting DSL Api Version to "+DEFAULT_VERSION); - } - } - - Response response; - SchemaVersion version = new SchemaVersion(versionParam); - - TransactionalGraphEngine dbEngine = null; - try { - String serverBase = req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); - traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); - traversalUriHttpEntry.setPaginationParameters(resultIndex, resultSize); - dbEngine = traversalUriHttpEntry.getDbEngine(); - JsonObject input = new JsonParser().parse(content).getAsJsonObject(); - JsonElement dslElement = input.get("dsl"); - String dsl = ""; - if (dslElement != null) { - dsl = dslElement.getAsString(); - } - - - boolean isDslOverride = dslOverride != null && !AAIConfig.get(TraversalConstants.DSL_OVERRIDE).equals("false") - && dslOverride.equals(AAIConfig.get(TraversalConstants.DSL_OVERRIDE)); - - if(isDslOverride) { - dslQueryProcessor.setStartNodeValidationFlag(false); - } - - dslQueryProcessor.setValidationRules(validate); - - Format format = Format.getFormat(queryFormat); - - if(isAggregate(format)){ - dslQueryProcessor.setAggregate(true); - } - - if(isHistory(format)){ - validateHistoryParams(format, info.getQueryParameters()); - } - - GraphTraversalSource traversalSource = getTraversalSource(dbEngine, format, info, roles); - - GenericQueryProcessor processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) - .queryFrom(dsl, "dsl").queryProcessor(dslQueryProcessor).version(dslApiVersion).processWith(processorType) - .format(format).uriParams(info.getQueryParameters()).traversalSource(isHistory(format), traversalSource).create(); - - SubGraphStyle subGraphStyle = SubGraphStyle.valueOf(subgraph); - List<Object> vertTemp = processor.execute(subGraphStyle); - - - // Dedup if duplicate objects are returned in each array in the aggregate format scenario. - List<Object> vertTempDedupedObjectList = dedupObjectInAggregateFormatResult(vertTemp); - - List <Object> vertices; - if (isAggregate(format)){ - vertices = traversalUriHttpEntry.getPaginatedVertexListForAggregateFormat(vertTempDedupedObjectList); - } else { - vertices = traversalUriHttpEntry.getPaginatedVertexList(vertTemp); - } - - DBSerializer serializer = new DBSerializer(version, dbEngine, ModelType.MOXY, sourceOfTruth); - FormatFactory ff = new FormatFactory(traversalUriHttpEntry.getLoader(), serializer, schemaVersions, - this.basePath, serverBase); - - MultivaluedMap<String, String> mvm = new MultivaluedHashMap<>(); - mvm.putAll(info.getQueryParameters()); - if (isHistory(format)) { - mvm.putSingle("startTs", Long.toString(getStartTime(format, mvm))); - mvm.putSingle("endTs", Long.toString(getEndTime(mvm))); - } - Formatter formatter = ff.get(format, mvm); - - final Map<String, List<String>> propertiesMap = processor.getPropertiesMap(); - String result = ""; - if (propertiesMap != null && !propertiesMap.isEmpty()){ - result = formatter.output(vertices, propertiesMap).toString(); - } - else { - result = formatter.output(vertices).toString(); - } - - String acceptType = headers.getHeaderString("Accept"); - - if(acceptType == null){ - acceptType = MediaType.APPLICATION_JSON; - } - - if(MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(acceptType))){ - result = xmlFormatTransformer.transform(result); - } - - if(traversalUriHttpEntry.isPaginated()){ - response = Response.status(Status.OK) - .type(acceptType) - .header("total-results", traversalUriHttpEntry.getTotalVertices()) - .header("total-pages", traversalUriHttpEntry.getTotalPaginationBuckets()) - .entity(result) - .build(); - }else { - response = Response.status(Status.OK) - .type(acceptType) - .entity(result).build(); - } - - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e); - } catch (SchemaViolationException sve) { - AAIException ex = new AAIException("AAI_4020", sve); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex); - } catch (Exception e) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex); - } finally { - if (dbEngine != null) { - dbEngine.rollback(); - } - - } - - return response; - } - - private List<Object> dedupObjectInAggregateFormatResult(List<Object> vertTemp) { - List<Object> vertTempDedupedObjectList = new ArrayList<Object>(); - Iterator<Object> itr = vertTemp.listIterator(); - while (itr.hasNext()){ - Object o = itr.next(); - if (o instanceof ArrayList) { - vertTempDedupedObjectList.add(((ArrayList) o).stream().distinct().collect(Collectors.toList())); - } - } - return vertTempDedupedObjectList; - } + private HttpEntry traversalUriHttpEntry; + + private QueryProcessorType processorType = QueryProcessorType.LOCAL_GROOVY; + + private static final Logger LOGGER = LoggerFactory.getLogger(DslConsumer.class); + + private DslQueryProcessor dslQueryProcessor; + + private SchemaVersions schemaVersions; + + private String basePath; + + private GremlinServerSingleton gremlinServerSingleton; + private final QueryVersion DEFAULT_VERSION = QueryVersion.V1; + private QueryVersion dslApiVersion = DEFAULT_VERSION; + + private XmlFormatTransformer xmlFormatTransformer; + + @Autowired + public DslConsumer(HttpEntry traversalUriHttpEntry, DslQueryProcessor dslQueryProcessor, + SchemaVersions schemaVersions, GremlinServerSingleton gremlinServerSingleton, + XmlFormatTransformer xmlFormatTransformer, + @Value("${schema.uri.base.path}") String basePath) { + this.traversalUriHttpEntry = traversalUriHttpEntry; + this.dslQueryProcessor = dslQueryProcessor; + this.schemaVersions = schemaVersions; + this.gremlinServerSingleton = gremlinServerSingleton; + this.xmlFormatTransformer = xmlFormatTransformer; + this.basePath = basePath; + } + + @PUT + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response executeQuery(String content, @PathParam("version") String versionParam, + @DefaultValue("graphson") @QueryParam("format") String queryFormat, + @DefaultValue("no_op") @QueryParam("subgraph") String subgraph, + @DefaultValue("all") @QueryParam("validate") String validate, @Context HttpHeaders headers, + @Context HttpServletRequest req, @Context UriInfo info, + @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, + @DefaultValue("-1") @QueryParam("resultSize") String resultSize) { + Set<String> roles = this.getRoles(req.getUserPrincipal()); + + 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() throws Exception { + return (processExecuteQuery(content, req, versionParam, queryFormat, subgraph, + validate, headers, info, resultIndex, resultSize, roles)); + } + }); + } + + public Response processExecuteQuery(String content, HttpServletRequest req, String versionParam, + String queryFormat, String subgraph, String validate, HttpHeaders headers, UriInfo info, + String resultIndex, String resultSize, Set<String> roles) { + + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String dslOverride = headers.getRequestHeaders().getFirst("X-DslOverride"); + + Optional<String> dslApiVersionHeader = + Optional.ofNullable(headers.getRequestHeaders().getFirst("X-DslApiVersion")); + if (dslApiVersionHeader.isPresent()) { + try { + dslApiVersion = QueryVersion.valueOf(dslApiVersionHeader.get()); + } catch (IllegalArgumentException e) { + LOGGER.debug("Defaulting DSL Api Version to " + DEFAULT_VERSION); + } + } + + Response response; + SchemaVersion version = new SchemaVersion(versionParam); + + TransactionalGraphEngine dbEngine = null; + try { + String serverBase = + req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); + traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); + traversalUriHttpEntry.setPaginationParameters(resultIndex, resultSize); + dbEngine = traversalUriHttpEntry.getDbEngine(); + JsonObject input = new JsonParser().parse(content).getAsJsonObject(); + JsonElement dslElement = input.get("dsl"); + String dsl = ""; + if (dslElement != null) { + dsl = dslElement.getAsString(); + } + + boolean isDslOverride = dslOverride != null + && !AAIConfig.get(TraversalConstants.DSL_OVERRIDE).equals("false") + && dslOverride.equals(AAIConfig.get(TraversalConstants.DSL_OVERRIDE)); + + if (isDslOverride) { + dslQueryProcessor.setStartNodeValidationFlag(false); + } + + dslQueryProcessor.setValidationRules(validate); + + Format format = Format.getFormat(queryFormat); + + if (isAggregate(format)) { + dslQueryProcessor.setAggregate(true); + } + + if (isHistory(format)) { + validateHistoryParams(format, info.getQueryParameters()); + } + + GraphTraversalSource traversalSource = + getTraversalSource(dbEngine, format, info, roles); + + GenericQueryProcessor processor = + new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) + .queryFrom(dsl, "dsl").queryProcessor(dslQueryProcessor).version(dslApiVersion) + .processWith(processorType).format(format).uriParams(info.getQueryParameters()) + .traversalSource(isHistory(format), traversalSource).create(); + + SubGraphStyle subGraphStyle = SubGraphStyle.valueOf(subgraph); + List<Object> vertTemp = processor.execute(subGraphStyle); + + // Dedup if duplicate objects are returned in each array in the aggregate format + // scenario. + List<Object> vertTempDedupedObjectList = dedupObjectInAggregateFormatResult(vertTemp); + + List<Object> vertices; + if (isAggregate(format)) { + vertices = traversalUriHttpEntry + .getPaginatedVertexListForAggregateFormat(vertTempDedupedObjectList); + } else { + vertices = traversalUriHttpEntry.getPaginatedVertexList(vertTemp); + } + + DBSerializer serializer = + new DBSerializer(version, dbEngine, ModelType.MOXY, sourceOfTruth); + FormatFactory ff = new FormatFactory(traversalUriHttpEntry.getLoader(), serializer, + schemaVersions, this.basePath, serverBase); + + MultivaluedMap<String, String> mvm = new MultivaluedHashMap<>(); + mvm.putAll(info.getQueryParameters()); + if (isHistory(format)) { + mvm.putSingle("startTs", Long.toString(getStartTime(format, mvm))); + mvm.putSingle("endTs", Long.toString(getEndTime(mvm))); + } + Formatter formatter = ff.get(format, mvm); + + final Map<String, List<String>> propertiesMap = processor.getPropertiesMap(); + String result = ""; + if (propertiesMap != null && !propertiesMap.isEmpty()) { + result = formatter.output(vertices, propertiesMap).toString(); + } else { + result = formatter.output(vertices).toString(); + } + + String acceptType = headers.getHeaderString("Accept"); + + if (acceptType == null) { + acceptType = MediaType.APPLICATION_JSON; + } + + if (MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(acceptType))) { + result = xmlFormatTransformer.transform(result); + } + + if (traversalUriHttpEntry.isPaginated()) { + response = Response.status(Status.OK).type(acceptType) + .header("total-results", traversalUriHttpEntry.getTotalVertices()) + .header("total-pages", traversalUriHttpEntry.getTotalPaginationBuckets()) + .entity(result).build(); + } else { + response = Response.status(Status.OK).type(acceptType).entity(result).build(); + } + + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e); + } catch (SchemaViolationException sve) { + AAIException ex = new AAIException("AAI_4020", sve); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex); + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex); + } finally { + if (dbEngine != null) { + dbEngine.rollback(); + } + + } + + return response; + } + + private List<Object> dedupObjectInAggregateFormatResult(List<Object> vertTemp) { + List<Object> vertTempDedupedObjectList = new ArrayList<Object>(); + Iterator<Object> itr = vertTemp.listIterator(); + while (itr.hasNext()) { + Object o = itr.next(); + if (o instanceof ArrayList) { + vertTempDedupedObjectList + .add(((ArrayList) o).stream().distinct().collect(Collectors.toList())); + } + } + return vertTempDedupedObjectList; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/ExceptionHandler.java b/aai-traversal/src/main/java/org/onap/aai/rest/ExceptionHandler.java index 452815e..d6d2f5e 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/ExceptionHandler.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/ExceptionHandler.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,6 +19,10 @@ */ package org.onap.aai.rest; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.sun.istack.SAXParseException2; + import java.util.ArrayList; import java.util.List; @@ -33,9 +37,6 @@ import javax.ws.rs.ext.Provider; import org.onap.aai.exceptions.AAIException; import org.onap.aai.logging.ErrorLogHelper; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.sun.istack.SAXParseException2; /** * The Class ExceptionHandler. @@ -43,84 +44,81 @@ import com.sun.istack.SAXParseException2; @Provider public class ExceptionHandler implements ExceptionMapper<Exception> { - private static final String AAI_4007 = "AAI_4007"; + private static final String AAI_4007 = "AAI_4007"; @Context private HttpServletRequest request; - + @Context private HttpHeaders headers; - + @Override public Response toResponse(Exception exception) { - Response response = null; - ArrayList<String> templateVars = new ArrayList<>(); + Response response = null; + ArrayList<String> templateVars = new ArrayList<>(); - //the general case is that cxf will give us a WebApplicationException - //with a linked exception - if (exception instanceof WebApplicationException) { - WebApplicationException e = (WebApplicationException) exception; - if (e.getCause() instanceof SAXParseException2) { - templateVars.add("UnmarshalException"); - AAIException ex = new AAIException(AAI_4007, exception); - response = Response - .status(400) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); + // the general case is that cxf will give us a WebApplicationException + // with a linked exception + if (exception instanceof WebApplicationException) { + WebApplicationException e = (WebApplicationException) exception; + if (e.getCause() instanceof SAXParseException2) { + templateVars.add("UnmarshalException"); + AAIException ex = new AAIException(AAI_4007, exception); + response = Response.status(400).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); - } - } else if (exception instanceof JsonParseException) { - //jackson does it differently so we get the direct JsonParseException - templateVars.add("JsonParseException"); - AAIException ex = new AAIException(AAI_4007, exception); - response = Response - .status(400) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); + } + } else if (exception instanceof JsonParseException) { + // jackson does it differently so we get the direct JsonParseException + templateVars.add("JsonParseException"); + AAIException ex = new AAIException(AAI_4007, exception); + response = Response + .status(400).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); } else if (exception instanceof JsonMappingException) { - //jackson does it differently so we get the direct JsonParseException - templateVars.add("JsonMappingException"); - AAIException ex = new AAIException(AAI_4007, exception); - response = Response - .status(400) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); - } - - // it didn't get set above, we wrap a general fault here - if (response == null) { - - Exception actual_e = exception; - if (exception instanceof WebApplicationException) { - WebApplicationException e = (WebApplicationException) exception; - response = e.getResponse(); - } else { - templateVars.add(request.getMethod()); - templateVars.add("unknown"); - AAIException ex = new AAIException("AAI_4000", actual_e); - List<MediaType> mediaTypes = headers.getAcceptableMediaTypes(); - int setError = 0; + // jackson does it differently so we get the direct JsonParseException + templateVars.add("JsonMappingException"); + AAIException ex = new AAIException(AAI_4007, exception); + response = Response + .status(400).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + } + + // it didn't get set above, we wrap a general fault here + if (response == null) { + + Exception actual_e = exception; + if (exception instanceof WebApplicationException) { + WebApplicationException e = (WebApplicationException) exception; + response = e.getResponse(); + } else { + templateVars.add(request.getMethod()); + templateVars.add("unknown"); + AAIException ex = new AAIException("AAI_4000", actual_e); + List<MediaType> mediaTypes = headers.getAcceptableMediaTypes(); + int setError = 0; - for (MediaType mediaType : mediaTypes) { - if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) { - response = Response - .status(400) - .type(MediaType.APPLICATION_XML_TYPE) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); - setError = 1; - } - } - if (setError == 0) { - response = Response - .status(400) - .type(MediaType.APPLICATION_JSON_TYPE) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); - } - } - } - return response; + for (MediaType mediaType : mediaTypes) { + if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) { + response = Response.status(400).type(MediaType.APPLICATION_XML_TYPE) + .entity(ErrorLogHelper.getRESTAPIErrorResponse( + headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + setError = 1; + } + } + if (setError == 0) { + response = Response.status(400).type(MediaType.APPLICATION_JSON_TYPE) + .entity(ErrorLogHelper.getRESTAPIErrorResponse( + headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + } + } + } + return response; } } 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 e015ec3..460065e 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -22,14 +22,24 @@ package org.onap.aai.rest; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; + import io.micrometer.core.annotation.Timed; + +import java.net.URI; +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; + import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.onap.aai.concurrent.AaiCallable; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.ModelType; import org.onap.aai.logging.ErrorLogHelper; - import org.onap.aai.parsers.query.QueryParser; import org.onap.aai.rest.db.HttpEntry; import org.onap.aai.rest.search.CustomQueryConfig; @@ -54,181 +64,178 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; -import java.net.URI; -import java.util.*; -import java.util.stream.Collectors; - @Path("{version: v[1-9][0-9]*|latest}/query") @Timed public class QueryConsumer extends TraversalConsumer { - private QueryProcessorType processorType = QueryProcessorType.LOCAL_GROOVY; - - private static final Logger LOGGER = LoggerFactory.getLogger(QueryConsumer.class); - - private HttpEntry traversalUriHttpEntry; - - - private SchemaVersions schemaVersions; - - private String basePath; - - private GremlinServerSingleton gremlinServerSingleton; - - private XmlFormatTransformer xmlFormatTransformer; - - @Autowired - public QueryConsumer(HttpEntry traversalUriHttpEntry, SchemaVersions schemaVersions, - GremlinServerSingleton gremlinServerSingleton, XmlFormatTransformer xmlFormatTransformer, @Value("${schema.uri.base.path}") String basePath) { - this.traversalUriHttpEntry = traversalUriHttpEntry; - this.schemaVersions = schemaVersions; - this.gremlinServerSingleton = gremlinServerSingleton; - this.basePath = basePath; - this.xmlFormatTransformer = xmlFormatTransformer; - } - - @PUT - @Consumes({ MediaType.APPLICATION_JSON}) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response executeQuery(String content, - @PathParam("version") String versionParam, - @DefaultValue("graphson") @QueryParam("format") String queryFormat, - @DefaultValue("no_op") @QueryParam("subgraph") String subgraph, - @Context HttpHeaders headers, - @Context HttpServletRequest req, - @Context UriInfo info, - @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, - @DefaultValue("-1") @QueryParam("resultSize") String resultSize) { - Set<String> roles = this.getRoles(req.getUserPrincipal()); - - return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, - TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, - TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, - headers, - info, - HttpMethod.GET, - new AaiCallable<Response>() { - @Override - public Response process() { - return processExecuteQuery(content, req, versionParam, queryFormat, subgraph, headers, info, resultIndex, resultSize, roles); - } - }); - } - - public Response processExecuteQuery(String content, HttpServletRequest req, String versionParam, String queryFormat, String subgraph, - HttpHeaders headers, UriInfo info, String resultIndex, - String resultSize, Set<String> roles) { - - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String queryProcessor = headers.getRequestHeaders().getFirst("QueryProcessor"); - QueryProcessorType processorType = this.processorType; - Response response; - TransactionalGraphEngine dbEngine = null; - - try { - this.checkQueryParams(info.getQueryParameters()); - Format format = Format.getFormat(queryFormat); - if (queryProcessor != null) { - processorType = QueryProcessorType.valueOf(queryProcessor); - } - SubGraphStyle subGraphStyle = SubGraphStyle.valueOf(subgraph); - - JsonParser parser = new JsonParser(); - JsonObject input = parser.parse(content).getAsJsonObject(); - JsonElement startElement = input.get("start"); - JsonElement queryElement = input.get("query"); - JsonElement gremlinElement = input.get("gremlin"); - List<URI> startURIs = new ArrayList<>(); - String queryURI = ""; - String gremlin = ""; - - SchemaVersion version = new SchemaVersion(versionParam); - String serverBase = req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); - traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); - /* - * Changes for Pagination - */ - - traversalUriHttpEntry.setPaginationParameters(resultIndex, resultSize); - dbEngine = traversalUriHttpEntry.getDbEngine(); - - if (startElement != null) { - - if (startElement.isJsonArray()) { - for (JsonElement element : startElement.getAsJsonArray()) { - startURIs.add(new URI(element.getAsString())); - } - } else { - startURIs.add(new URI(startElement.getAsString())); - } - } - if (queryElement != null) { - queryURI = queryElement.getAsString(); - } - if (gremlinElement != null) { - gremlin = gremlinElement.getAsString(); - } - URI queryURIObj = new URI(queryURI); - - CustomQueryConfig customQueryConfig = getCustomQueryConfig(queryURIObj); - if ( customQueryConfig != null ) { - List<String> missingRequiredQueryParameters = checkForMissingQueryParameters( customQueryConfig.getQueryRequiredProperties(), URITools.getQueryMap(queryURIObj)); - - if ( !missingRequiredQueryParameters.isEmpty() ) { - return( createMessageMissingQueryRequiredParameters( missingRequiredQueryParameters, headers)); - } - - List<String> invalidQueryParameters = checkForInvalidQueryParameters( customQueryConfig, URITools.getQueryMap(queryURIObj)); - - if ( !invalidQueryParameters.isEmpty() ) { - return( createMessageInvalidQueryParameters( invalidQueryParameters, headers)); - } - - } else if ( queryElement != null ) { - return (createMessageInvalidQuerySection(queryURI, headers)); - } - - GenericQueryProcessor processor; - - if(isHistory(format)){ - validateHistoryParams(format, info.getQueryParameters()); - } - GraphTraversalSource traversalSource = getTraversalSource(dbEngine, format, info, roles); - QueryStyle queryStyle = getQueryStyle(format, traversalUriHttpEntry); - - if (!startURIs.isEmpty()) { - Set<Vertex> vertexSet = new LinkedHashSet<>(); - QueryParser uriQuery; - List<Vertex> vertices; - for (URI startUri : startURIs) { - uriQuery = dbEngine.getQueryBuilder(queryStyle, traversalSource).createQueryFromURI(startUri, URITools.getQueryMap(startUri)); - vertices = uriQuery.getQueryBuilder().toList(); - vertexSet.addAll(vertices); - } - - processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) - .startFrom(vertexSet).queryFrom(queryURIObj).format(format) - .processWith(processorType).traversalSource(isHistory(format), traversalSource).create(); - } else if (!queryURI.equals("")){ - processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) - .queryFrom(queryURIObj) - .processWith(processorType).traversalSource(isHistory(format), traversalSource).create(); - } else { - processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) - .queryFrom(gremlin, "gremlin") - .processWith(processorType).traversalSource(isHistory(format), traversalSource).create(); - } - List<Object> vertTemp = processor.execute(subGraphStyle); - List<Object> vertices = traversalUriHttpEntry.getPaginatedVertexList(vertTemp); - - DBSerializer serializer = new DBSerializer(version, dbEngine, ModelType.MOXY, sourceOfTruth); - FormatFactory ff = new FormatFactory(traversalUriHttpEntry.getLoader(), serializer, schemaVersions, this.basePath, serverBase); - - MultivaluedMap<String, String> mvm = new MultivaluedHashMap<>(); + private QueryProcessorType processorType = QueryProcessorType.LOCAL_GROOVY; + + private static final Logger LOGGER = LoggerFactory.getLogger(QueryConsumer.class); + + private HttpEntry traversalUriHttpEntry; + + private SchemaVersions schemaVersions; + + private String basePath; + + private GremlinServerSingleton gremlinServerSingleton; + + private XmlFormatTransformer xmlFormatTransformer; + + @Autowired + public QueryConsumer(HttpEntry traversalUriHttpEntry, SchemaVersions schemaVersions, + GremlinServerSingleton gremlinServerSingleton, XmlFormatTransformer xmlFormatTransformer, + @Value("${schema.uri.base.path}") String basePath) { + this.traversalUriHttpEntry = traversalUriHttpEntry; + this.schemaVersions = schemaVersions; + this.gremlinServerSingleton = gremlinServerSingleton; + this.basePath = basePath; + this.xmlFormatTransformer = xmlFormatTransformer; + } + + @PUT + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response executeQuery(String content, @PathParam("version") String versionParam, + @DefaultValue("graphson") @QueryParam("format") String queryFormat, + @DefaultValue("no_op") @QueryParam("subgraph") String subgraph, + @Context HttpHeaders headers, @Context HttpServletRequest req, @Context UriInfo info, + @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex, + @DefaultValue("-1") @QueryParam("resultSize") String resultSize) { + Set<String> roles = this.getRoles(req.getUserPrincipal()); + + return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, + new AaiCallable<Response>() { + @Override + public Response process() { + return processExecuteQuery(content, req, versionParam, queryFormat, subgraph, + headers, info, resultIndex, resultSize, roles); + } + }); + } + + public Response processExecuteQuery(String content, HttpServletRequest req, String versionParam, + String queryFormat, String subgraph, HttpHeaders headers, UriInfo info, String resultIndex, + String resultSize, Set<String> roles) { + + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String queryProcessor = headers.getRequestHeaders().getFirst("QueryProcessor"); + QueryProcessorType processorType = this.processorType; + Response response; + TransactionalGraphEngine dbEngine = null; + + try { + this.checkQueryParams(info.getQueryParameters()); + Format format = Format.getFormat(queryFormat); + if (queryProcessor != null) { + processorType = QueryProcessorType.valueOf(queryProcessor); + } + SubGraphStyle subGraphStyle = SubGraphStyle.valueOf(subgraph); + + JsonParser parser = new JsonParser(); + JsonObject input = parser.parse(content).getAsJsonObject(); + JsonElement startElement = input.get("start"); + JsonElement queryElement = input.get("query"); + JsonElement gremlinElement = input.get("gremlin"); + List<URI> startURIs = new ArrayList<>(); + String queryURI = ""; + String gremlin = ""; + + SchemaVersion version = new SchemaVersion(versionParam); + String serverBase = + req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); + traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); + /* + * Changes for Pagination + */ + + traversalUriHttpEntry.setPaginationParameters(resultIndex, resultSize); + dbEngine = traversalUriHttpEntry.getDbEngine(); + + if (startElement != null) { + + if (startElement.isJsonArray()) { + for (JsonElement element : startElement.getAsJsonArray()) { + startURIs.add(new URI(element.getAsString())); + } + } else { + startURIs.add(new URI(startElement.getAsString())); + } + } + if (queryElement != null) { + queryURI = queryElement.getAsString(); + } + if (gremlinElement != null) { + gremlin = gremlinElement.getAsString(); + } + URI queryURIObj = new URI(queryURI); + + CustomQueryConfig customQueryConfig = getCustomQueryConfig(queryURIObj); + if (customQueryConfig != null) { + List<String> missingRequiredQueryParameters = + checkForMissingQueryParameters(customQueryConfig.getQueryRequiredProperties(), + URITools.getQueryMap(queryURIObj)); + + if (!missingRequiredQueryParameters.isEmpty()) { + return (createMessageMissingQueryRequiredParameters( + missingRequiredQueryParameters, headers)); + } + + List<String> invalidQueryParameters = checkForInvalidQueryParameters( + customQueryConfig, URITools.getQueryMap(queryURIObj)); + + if (!invalidQueryParameters.isEmpty()) { + return (createMessageInvalidQueryParameters(invalidQueryParameters, headers)); + } + + } else if (queryElement != null) { + return (createMessageInvalidQuerySection(queryURI, headers)); + } + + GenericQueryProcessor processor; + + if (isHistory(format)) { + validateHistoryParams(format, info.getQueryParameters()); + } + GraphTraversalSource traversalSource = + getTraversalSource(dbEngine, format, info, roles); + QueryStyle queryStyle = getQueryStyle(format, traversalUriHttpEntry); + + if (!startURIs.isEmpty()) { + Set<Vertex> vertexSet = new LinkedHashSet<>(); + QueryParser uriQuery; + List<Vertex> vertices; + for (URI startUri : startURIs) { + uriQuery = dbEngine.getQueryBuilder(queryStyle, traversalSource) + .createQueryFromURI(startUri, URITools.getQueryMap(startUri)); + vertices = uriQuery.getQueryBuilder().toList(); + vertexSet.addAll(vertices); + } + + processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) + .startFrom(vertexSet).queryFrom(queryURIObj).format(format) + .processWith(processorType).traversalSource(isHistory(format), traversalSource) + .create(); + } else if (!queryURI.equals("")) { + processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) + .queryFrom(queryURIObj).processWith(processorType) + .traversalSource(isHistory(format), traversalSource).create(); + } else { + processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) + .queryFrom(gremlin, "gremlin").processWith(processorType) + .traversalSource(isHistory(format), traversalSource).create(); + } + List<Object> vertTemp = processor.execute(subGraphStyle); + List<Object> vertices = traversalUriHttpEntry.getPaginatedVertexList(vertTemp); + + DBSerializer serializer = + new DBSerializer(version, dbEngine, ModelType.MOXY, sourceOfTruth); + FormatFactory ff = new FormatFactory(traversalUriHttpEntry.getLoader(), serializer, + schemaVersions, this.basePath, serverBase); + + MultivaluedMap<String, String> mvm = new MultivaluedHashMap<>(); mvm.putAll(info.getQueryParameters()); if (isHistory(format)) { mvm.putSingle("startTs", Long.toString(getStartTime(format, mvm))); @@ -236,142 +243,139 @@ public class QueryConsumer extends TraversalConsumer { } Formatter formatter = ff.get(format, mvm); - String result = formatter.output(vertices).toString(); - - String acceptType = headers.getHeaderString("Accept"); - - if(acceptType == null){ - acceptType = MediaType.APPLICATION_JSON; - } - - if(MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(acceptType))){ - result = xmlFormatTransformer.transform(result); - } - - if(traversalUriHttpEntry.isPaginated()){ - response = Response.status(Status.OK) - .type(acceptType) - .header("total-results", traversalUriHttpEntry.getTotalVertices()) - .header("total-pages", traversalUriHttpEntry.getTotalPaginationBuckets()) - .entity(result) - .build(); - }else { - response = Response.status(Status.OK) - .type(acceptType) - .entity(result).build(); - } - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); - } catch (Exception e ) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); - } finally { - if (dbEngine != null) { - dbEngine.rollback(); - } - - } - - return response; - } - - public void checkQueryParams(MultivaluedMap<String, String> params) throws AAIException { - - if (params.containsKey("depth") && params.getFirst("depth").matches("\\d+")) { - String depth = params.getFirst("depth"); - int i = Integer.parseInt(depth); - if (i > 1) { - throw new AAIException("AAI_3303"); - } - } - - - } - - private List<String> checkForMissingQueryParameters( List<String> requiredParameters, MultivaluedMap<String, String> queryParams ) { - List<String> result = new ArrayList<>(); - - for ( String param : requiredParameters ) { - if ( !queryParams.containsKey(param)) { - result.add(param); - } - } - return result; - } - - private CustomQueryConfig getCustomQueryConfig(URI uriObj ) { - String path = uriObj.getPath(); - - String[] parts = path.split("/"); - boolean hasQuery = false; - for ( String part:parts ) { - if ( hasQuery) { - return gremlinServerSingleton.getCustomQueryConfig(part); - } - if ( "query".equals(part)) { - hasQuery = true; - } - } - - return null; - - } - - private Response createMessageMissingQueryRequiredParameters(List<String> missingRequiredQueryParams, HttpHeaders headers) { - AAIException e = new AAIException("AAI_3013"); - - ArrayList<String> templateVars = new ArrayList<>(); - templateVars.add(missingRequiredQueryParams.toString()); - - return Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, - templateVars)).build(); - } - - private Response createMessageInvalidQuerySection(String invalidQuery, HttpHeaders headers) { - AAIException e = new AAIException("AAI_3014"); - - ArrayList<String> templateVars = new ArrayList<>(); - templateVars.add(invalidQuery); - - return Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, - templateVars)).build(); - } - - - private List<String> checkForInvalidQueryParameters( CustomQueryConfig customQueryConfig, MultivaluedMap<String, String> queryParams) { - - List<String> 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<>(); - } - return queryParams.keySet().stream() - .filter(param -> !allParameters.contains(param)) - .collect(Collectors.toList()); - } - - private Response createMessageInvalidQueryParameters(List<String> invalidQueryParams, HttpHeaders headers) { - AAIException e = new AAIException("AAI_3022"); - - ArrayList<String> templateVars = new ArrayList<>(); - templateVars.add(invalidQueryParams.toString()); - - return Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse( - headers.getAcceptableMediaTypes(), - e, - templateVars)).build(); - - } + String result = formatter.output(vertices).toString(); + + String acceptType = headers.getHeaderString("Accept"); + + if (acceptType == null) { + acceptType = MediaType.APPLICATION_JSON; + } + + if (MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(acceptType))) { + result = xmlFormatTransformer.transform(result); + } + + if (traversalUriHttpEntry.isPaginated()) { + response = Response.status(Status.OK).type(acceptType) + .header("total-results", traversalUriHttpEntry.getTotalVertices()) + .header("total-pages", traversalUriHttpEntry.getTotalPaginationBuckets()) + .entity(result).build(); + } else { + response = Response.status(Status.OK).type(acceptType).entity(result).build(); + } + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); + } finally { + if (dbEngine != null) { + dbEngine.rollback(); + } + + } + + return response; + } + + public void checkQueryParams(MultivaluedMap<String, String> params) throws AAIException { + + if (params.containsKey("depth") && params.getFirst("depth").matches("\\d+")) { + String depth = params.getFirst("depth"); + int i = Integer.parseInt(depth); + if (i > 1) { + throw new AAIException("AAI_3303"); + } + } + + } + + private List<String> checkForMissingQueryParameters(List<String> requiredParameters, + MultivaluedMap<String, String> queryParams) { + List<String> result = new ArrayList<>(); + + for (String param : requiredParameters) { + if (!queryParams.containsKey(param)) { + result.add(param); + } + } + return result; + } + + private CustomQueryConfig getCustomQueryConfig(URI uriObj) { + String path = uriObj.getPath(); + + String[] parts = path.split("/"); + boolean hasQuery = false; + for (String part : parts) { + if (hasQuery) { + return gremlinServerSingleton.getCustomQueryConfig(part); + } + if ("query".equals(part)) { + hasQuery = true; + } + } + + return null; + + } + + private Response createMessageMissingQueryRequiredParameters( + List<String> missingRequiredQueryParams, HttpHeaders headers) { + AAIException e = new AAIException("AAI_3013"); + + ArrayList<String> templateVars = new ArrayList<>(); + templateVars.add(missingRequiredQueryParams.toString()); + + return Response + .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); + } + + private Response createMessageInvalidQuerySection(String invalidQuery, HttpHeaders headers) { + AAIException e = new AAIException("AAI_3014"); + + ArrayList<String> templateVars = new ArrayList<>(); + templateVars.add(invalidQuery); + + return Response + .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); + } + + private List<String> checkForInvalidQueryParameters(CustomQueryConfig customQueryConfig, + MultivaluedMap<String, String> queryParams) { + + List<String> 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<>(); + } + return queryParams.keySet().stream().filter(param -> !allParameters.contains(param)) + .collect(Collectors.toList()); + } + + private Response createMessageInvalidQueryParameters(List<String> invalidQueryParams, + HttpHeaders headers) { + AAIException e = new AAIException("AAI_3022"); + + ArrayList<String> templateVars = new ArrayList<>(); + templateVars.add(invalidQueryParams.toString()); + + return Response + .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); + + } } 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 7ec20bc..7f40979 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,11 +20,19 @@ package org.onap.aai.rest; import io.micrometer.core.annotation.Timed; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; + import org.onap.aai.concurrent.AaiCallable; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.ModelType; import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; - import org.onap.aai.rest.db.HttpEntry; import org.onap.aai.rest.search.GenericQueryProcessor; import org.onap.aai.rest.search.GremlinServerSingleton; @@ -47,209 +55,205 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -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("/recents/{version: v[1-9][0-9]*|latest}") @Timed public class RecentAPIConsumer extends RESTAPI { private static final String AAI_3021 = "AAI_3021"; - - /** The introspector factory type. */ - private ModelType introspectorFactoryType = ModelType.MOXY; - - private QueryProcessorType processorType = QueryProcessorType.LOCAL_GROOVY; - /** The query style. */ - - private static final Logger LOGGER = LoggerFactory.getLogger(RecentAPIConsumer.class); - - private HttpEntry traversalUriHttpEntry; - - private SchemaVersions schemaVersions; - - private String basePath; - - private GremlinServerSingleton gremlinServerSingleton; - - private XmlFormatTransformer xmlFormatTransformer; - - - @Autowired - public RecentAPIConsumer( - HttpEntry traversalUriHttpEntry, - SchemaVersions schemaVersions, - GremlinServerSingleton gremlinServerSingleton, - XmlFormatTransformer xmlFormatTransformer, - @Value("${schema.uri.base.path}") String basePath - ){ - this.traversalUriHttpEntry = traversalUriHttpEntry; - this.schemaVersions = schemaVersions; - this.gremlinServerSingleton = gremlinServerSingleton; - this.xmlFormatTransformer = xmlFormatTransformer; - this.basePath = basePath; - } - - @GET - @Path("/{nodeType: .+}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - public Response getRecentData(String content, - @PathParam("version") String versionParam, - @PathParam("nodeType") String nodeType, - @Context HttpHeaders headers, - @Context HttpServletRequest req, - @Context UriInfo info) { - - return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, - TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, new AaiCallable<Response>() { - @Override - public Response process() { - return processRecentData(content, req, versionParam, nodeType, info, headers); - } - }); - - } - - public Response processRecentData(String content, HttpServletRequest req, @PathParam("version") String versionParam, - @PathParam("nodeType") String nodeType, @Context UriInfo info, @Context HttpHeaders headers) { - - String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - String queryProcessor = headers.getRequestHeaders().getFirst("QueryProcessor"); - QueryProcessorType processorType = this.processorType; - Response response; - TransactionalGraphEngine dbEngine = null; - try { - - if (queryProcessor != null) { - processorType = QueryProcessorType.valueOf(queryProcessor); - } - - SchemaVersion version = new SchemaVersion(versionParam); - this.checkVersion(version); - - String serverBase = req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); - traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); - dbEngine = traversalUriHttpEntry.getDbEngine(); - - /* - * Check for mandatory parameters here - */ - - this.checkNodeType(nodeType); - this.checkQueryParams(info.getQueryParameters()); - - GenericQueryProcessor processor = null; - - - - processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton).queryFrom(nodeType, "nodeQuery") - .uriParams(info.getQueryParameters()) - .processWith(processorType).create(); - - - - String result = ""; - SubGraphStyle subGraphStyle = null; - List<Object> vertices = processor.execute(subGraphStyle); - - DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth); - FormatFactory ff = new FormatFactory(traversalUriHttpEntry.getLoader(), serializer, schemaVersions, this.basePath, serverBase); + + /** The introspector factory type. */ + private ModelType introspectorFactoryType = ModelType.MOXY; + + private QueryProcessorType processorType = QueryProcessorType.LOCAL_GROOVY; + /** The query style. */ + + private static final Logger LOGGER = LoggerFactory.getLogger(RecentAPIConsumer.class); + + private HttpEntry traversalUriHttpEntry; + + private SchemaVersions schemaVersions; + + private String basePath; + + private GremlinServerSingleton gremlinServerSingleton; + + private XmlFormatTransformer xmlFormatTransformer; + + @Autowired + public RecentAPIConsumer(HttpEntry traversalUriHttpEntry, SchemaVersions schemaVersions, + GremlinServerSingleton gremlinServerSingleton, XmlFormatTransformer xmlFormatTransformer, + @Value("${schema.uri.base.path}") String basePath) { + this.traversalUriHttpEntry = traversalUriHttpEntry; + this.schemaVersions = schemaVersions; + this.gremlinServerSingleton = gremlinServerSingleton; + this.xmlFormatTransformer = xmlFormatTransformer; + this.basePath = basePath; + } + + @GET + @Path("/{nodeType: .+}") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response getRecentData(String content, @PathParam("version") String versionParam, + @PathParam("nodeType") String nodeType, @Context HttpHeaders headers, + @Context HttpServletRequest req, @Context UriInfo info) { + + return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, + new AaiCallable<Response>() { + @Override + public Response process() { + return processRecentData(content, req, versionParam, nodeType, info, headers); + } + }); + + } + + public Response processRecentData(String content, HttpServletRequest req, + @PathParam("version") String versionParam, @PathParam("nodeType") String nodeType, + @Context UriInfo info, @Context HttpHeaders headers) { + + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String queryProcessor = headers.getRequestHeaders().getFirst("QueryProcessor"); + QueryProcessorType processorType = this.processorType; + Response response; + TransactionalGraphEngine dbEngine = null; + try { + + if (queryProcessor != null) { + processorType = QueryProcessorType.valueOf(queryProcessor); + } + + SchemaVersion version = new SchemaVersion(versionParam); + this.checkVersion(version); + + String serverBase = + req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/"); + traversalUriHttpEntry.setHttpEntryProperties(version, serverBase); + dbEngine = traversalUriHttpEntry.getDbEngine(); + + /* + * Check for mandatory parameters here + */ + + this.checkNodeType(nodeType); + this.checkQueryParams(info.getQueryParameters()); + + GenericQueryProcessor processor = null; + + processor = new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton) + .queryFrom(nodeType, "nodeQuery").uriParams(info.getQueryParameters()) + .processWith(processorType).create(); + + String result = ""; + SubGraphStyle subGraphStyle = null; + List<Object> vertices = processor.execute(subGraphStyle); + + DBSerializer serializer = + new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth); + FormatFactory ff = new FormatFactory(traversalUriHttpEntry.getLoader(), serializer, + schemaVersions, this.basePath, serverBase); Format format = Format.pathed_resourceversion; - - Formatter formater = ff.get(format, info.getQueryParameters()); - - result = formater.output(vertices).toString(); - - //LOGGER.info("Completed"); - - String acceptType = headers.getHeaderString("Accept"); - - if(acceptType == null){ - acceptType = MediaType.APPLICATION_JSON; - } - - if(MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(acceptType))){ - result = xmlFormatTransformer.transform(result); - } - - response = Response.status(Status.OK).type(acceptType).entity(result).build(); - - } catch (AAIException e) { - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); - } catch (Exception e) { - AAIException ex = new AAIException("AAI_4000", e); - response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); - } finally { - - if (dbEngine != null) { - dbEngine.rollback(); - } - - } - - return response; - } - - private void checkVersion(SchemaVersion version) throws AAIException { - if(!schemaVersions.getVersions().contains(version)){ - throw new AAIException(AAI_3021, "Schema Version is not valid"); - } - } - - public void checkNodeType(String nodeType) throws AAIException { - try { - traversalUriHttpEntry.getLoader().introspectorFromName(nodeType); - } catch (AAIUnknownObjectException e) { - throw new AAIException("AAI_6115", "Unrecognized nodeType [" + nodeType + "] passed to recents query."); - } - } - public void checkQueryParams(MultivaluedMap<String, String> params) throws AAIException { - - boolean isHoursParameter = false; - boolean isDateTimeParameter = false; - - if (params != null && params.containsKey("hours") && params.getFirst("hours").matches("-?\\d+")) { - isHoursParameter = true; - long hours; - 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); - } - } - 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; - 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() ); - } - } - - if(!isHoursParameter && !isDateTimeParameter){ - throw new AAIException(AAI_3021, "Send valid hours or date-time to specify the timebounds"); - } - - if(isHoursParameter && isDateTimeParameter){ - throw new AAIException(AAI_3021, "Send either hours or date-time and not both to specify the timebounds"); - } - - - } + + Formatter formater = ff.get(format, info.getQueryParameters()); + + result = formater.output(vertices).toString(); + + // LOGGER.info("Completed"); + + String acceptType = headers.getHeaderString("Accept"); + + if (acceptType == null) { + acceptType = MediaType.APPLICATION_JSON; + } + + if (MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(acceptType))) { + result = xmlFormatTransformer.transform(result); + } + + response = Response.status(Status.OK).type(acceptType).entity(result).build(); + + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); + } catch (Exception e) { + AAIException ex = new AAIException("AAI_4000", e); + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); + } finally { + + if (dbEngine != null) { + dbEngine.rollback(); + } + + } + + return response; + } + + private void checkVersion(SchemaVersion version) throws AAIException { + if (!schemaVersions.getVersions().contains(version)) { + throw new AAIException(AAI_3021, "Schema Version is not valid"); + } + } + + public void checkNodeType(String nodeType) throws AAIException { + try { + traversalUriHttpEntry.getLoader().introspectorFromName(nodeType); + } catch (AAIUnknownObjectException e) { + throw new AAIException("AAI_6115", + "Unrecognized nodeType [" + nodeType + "] passed to recents query."); + } + } + + public void checkQueryParams(MultivaluedMap<String, String> params) throws AAIException { + + boolean isHoursParameter = false; + boolean isDateTimeParameter = false; + + if (params != null && params.containsKey("hours") + && params.getFirst("hours").matches("-?\\d+")) { + isHoursParameter = true; + long hours; + 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); + } + } + 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; + 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()); + } + } + + if (!isHoursParameter && !isDateTimeParameter) { + throw new AAIException(AAI_3021, + "Send valid hours or date-time to specify the timebounds"); + } + + if (isHoursParameter && isDateTimeParameter) { + throw new AAIException(AAI_3021, + "Send either hours or date-time and not both to specify the timebounds"); + } + + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java b/aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java index a8f88ec..2980f28 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,6 +19,15 @@ */ package org.onap.aai.rest; +import java.security.Principal; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; + import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.tinkerpop.gremlin.process.traversal.P; @@ -37,14 +46,6 @@ import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.serialization.queryformats.Format; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.UriInfo; -import java.security.Principal; -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - public abstract class TraversalConsumer extends RESTAPI { private static final String HISTORICAL_FORMAT = "state,lifecycle"; @@ -57,12 +58,12 @@ public abstract class TraversalConsumer extends RESTAPI { private Long furthestInThePast = null; public TraversalConsumer() { - this.historyTruncateWindow = Integer.parseInt( - SpringContextAware.getApplicationContext().getEnvironment().getProperty("history.truncate.window.days", "365")); - this.historyEnabled = Boolean.parseBoolean( - SpringContextAware.getApplicationContext().getEnvironment().getProperty("history.enabled", "false")); - this.multiTenancyEnabled = Boolean.parseBoolean( - SpringContextAware.getApplicationContext().getEnvironment().getProperty("multi.tenancy.enabled", "false")); + this.historyTruncateWindow = Integer.parseInt(SpringContextAware.getApplicationContext() + .getEnvironment().getProperty("history.truncate.window.days", "365")); + this.historyEnabled = Boolean.parseBoolean(SpringContextAware.getApplicationContext() + .getEnvironment().getProperty("history.enabled", "false")); + this.multiTenancyEnabled = Boolean.parseBoolean(SpringContextAware.getApplicationContext() + .getEnvironment().getProperty("multi.tenancy.enabled", "false")); } public boolean isHistory(Format queryFormat) { @@ -84,85 +85,60 @@ public abstract class TraversalConsumer extends RESTAPI { } else if (Format.lifecycle.equals(format)) { return getLifeCycleSubgraphStrategy(startTs, endTs); } else { - return SubgraphStrategy.build() - .vertices(__.has(AAIProperties.START_TS, P.gte(startTs))) - .vertexProperties(__.has(AAIProperties.START_TS, P.gte(startTs))) - .edges(__.has(AAIProperties.START_TS, P.gte(startTs))).create(); + return SubgraphStrategy.build().vertices(__.has(AAIProperties.START_TS, P.gte(startTs))) + .vertexProperties(__.has(AAIProperties.START_TS, P.gte(startTs))) + .edges(__.has(AAIProperties.START_TS, P.gte(startTs))).create(); } } private SubgraphStrategy getLifeCycleSubgraphStrategy(long startTs, long endTs) { return SubgraphStrategy.build() - .vertices( - __.not( - __.or( - __.and( - __.has(AAIProperties.START_TS, P.gt(startTs)), - __.has(AAIProperties.START_TS, P.gt(endTs)) - ), - __.and( - __.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(startTs)), - __.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(endTs)) - ) - ) - ) - ).vertexProperties( - __.not( - __.or( - __.and( - __.has(AAIProperties.START_TS, P.gt(startTs)), - __.has(AAIProperties.START_TS, P.gt(endTs)) - ), - __.and( - __.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(startTs)), - __.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(endTs)) - ) - ) - ) - ).edges( - __.not( - __.or( - __.and( - __.has(AAIProperties.START_TS, P.gt(startTs)), - __.has(AAIProperties.START_TS, P.gt(endTs)) - ), - __.and( - __.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(startTs)), - __.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(endTs)) - ) - ) - ) - ).create(); + .vertices(__.not(__.or( + __.and(__.has(AAIProperties.START_TS, P.gt(startTs)), + __.has(AAIProperties.START_TS, P.gt(endTs))), + __.and(__.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(startTs)), + __.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(endTs)))))) + .vertexProperties(__.not(__.or( + __.and(__.has(AAIProperties.START_TS, P.gt(startTs)), + __.has(AAIProperties.START_TS, P.gt(endTs))), + __.and(__.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(startTs)), + __.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(endTs)))))) + .edges(__.not(__.or( + __.and(__.has(AAIProperties.START_TS, P.gt(startTs)), + __.has(AAIProperties.START_TS, P.gt(endTs))), + __.and(__.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(startTs)), + __.has(AAIProperties.END_TS).has(AAIProperties.END_TS, P.lt(endTs)))))) + .create(); } private SubgraphStrategy getStateSubgraphStrategy(long startTs) { return SubgraphStrategy.build() - .vertices( - __.and(__.has(AAIProperties.START_TS, P.lte(startTs)), - __.or(__.hasNot(AAIProperties.END_TS), __.has(AAIProperties.END_TS, P.gt(startTs)))) - ).vertexProperties( - __.and(__.has(AAIProperties.START_TS, P.lte(startTs)), - __.or(__.hasNot(AAIProperties.END_TS), __.has(AAIProperties.END_TS, P.gt(startTs)))) - ).edges( - __.and(__.has(AAIProperties.START_TS, P.lte(startTs)), - __.or(__.hasNot(AAIProperties.END_TS), __.has(AAIProperties.END_TS, P.gt(startTs)))) - ).create(); + .vertices(__.and(__.has(AAIProperties.START_TS, P.lte(startTs)), + __.or(__.hasNot(AAIProperties.END_TS), + __.has(AAIProperties.END_TS, P.gt(startTs))))) + .vertexProperties(__.and(__.has(AAIProperties.START_TS, P.lte(startTs)), + __.or(__.hasNot(AAIProperties.END_TS), + __.has(AAIProperties.END_TS, P.gt(startTs))))) + .edges(__.and(__.has(AAIProperties.START_TS, P.lte(startTs)), __ + .or(__.hasNot(AAIProperties.END_TS), __.has(AAIProperties.END_TS, P.gt(startTs))))) + .create(); } private SubgraphStrategy getDataOwnerSubgraphStrategy(Set<String> roles) { return SubgraphStrategy.build() - .vertices( - __.or(__.has("data-owner", P.within(roles)), __.hasNot("data-owner")) - ).create(); + .vertices(__.or(__.has("data-owner", P.within(roles)), __.hasNot("data-owner"))) + .create(); } - protected GraphTraversalSource getTraversalSource(TransactionalGraphEngine dbEngine, Format format, UriInfo info, Set<String> roles) throws AAIException { + protected GraphTraversalSource getTraversalSource(TransactionalGraphEngine dbEngine, + Format format, UriInfo info, Set<String> roles) throws AAIException { GraphTraversalSource traversalSource; if (isHistory(format)) { long localStartTime = this.getStartTime(format, info.getQueryParameters()); long localEndTime = this.getEndTime(info.getQueryParameters()); - traversalSource = dbEngine.asAdmin().getTraversalSource().withStrategies(getSubgraphStrategy(localStartTime, localEndTime, format)); + traversalSource = dbEngine.asAdmin().getTraversalSource() + .withStrategies(getSubgraphStrategy(localStartTime, localEndTime, format)); } else { traversalSource = dbEngine.asAdmin().getTraversalSource(); @@ -185,13 +161,13 @@ public abstract class TraversalConsumer extends RESTAPI { return Collections.EMPTY_SET; } - return account.getRoles() - .stream() - .map(role -> StringUtils.removeEnd(role, OwnerCheck.READ_ONLY_SUFFIX)) - .collect(Collectors.toSet()); + return account.getRoles().stream() + .map(role -> StringUtils.removeEnd(role, OwnerCheck.READ_ONLY_SUFFIX)) + .collect(Collectors.toSet()); } - protected void validateHistoryParams(Format format, MultivaluedMap<String, String> params) throws AAIException { + protected void validateHistoryParams(Format format, MultivaluedMap<String, String> params) + throws AAIException { getStartTime(format, params); getEndTime(params); } @@ -199,31 +175,37 @@ public abstract class TraversalConsumer extends RESTAPI { /** * If a request comes in for information prior to our truncation timeframe, throw an error. * In the changes api, we never return change timestamps prior to the truncation timeframe. - * In the lifecycle api, we should treat a call with no timestamp as a lifecycle since call with a timestamp of the truncation time - * in the lifecycle api, we should return an error if the timestamp provided is prior to the truncation time - * In the state api, we should return an error if the timestamp provided is prior to the truncation time + * In the lifecycle api, we should treat a call with no timestamp as a lifecycle since call with + * a timestamp of the truncation time + * in the lifecycle api, we should return an error if the timestamp provided is prior to the + * truncation time + * In the state api, we should return an error if the timestamp provided is prior to the + * truncation time + * * @param params * @return */ - protected long getStartTime(Format format, MultivaluedMap<String, String> params) throws AAIException { + protected long getStartTime(Format format, MultivaluedMap<String, String> params) + throws AAIException { if (startTime != null) { return startTime; } - String startTs = params.getFirst("startTs") ; + String startTs = params.getFirst("startTs"); if (Format.state.equals(format)) { - if (startTs == null || startTs.isEmpty() || "-1".equals(startTs) || "now".equals(startTs)) { + if (startTs == null || startTs.isEmpty() || "-1".equals(startTs) + || "now".equals(startTs)) { startTime = currentTime; } else { startTime = Long.valueOf(startTs); verifyTimeAgainstTruncationTime(startTime); } } else if (Format.lifecycle.equals(format)) { - if("now".equals(startTs)) { + if ("now".equals(startTs)) { startTime = currentTime; - } else if (startTs == null || startTs.isEmpty()|| "-1".equals(startTs)) { + } else if (startTs == null || startTs.isEmpty() || "-1".equals(startTs)) { startTime = getFurthestInThePast(); } else { startTime = Long.valueOf(startTs); @@ -246,7 +228,7 @@ public abstract class TraversalConsumer extends RESTAPI { return endTime; } - String endTs = params.getFirst("endTs") ; + String endTs = params.getFirst("endTs"); if (endTs == null || endTs.isEmpty() || "-1".equals(endTs) || "now".equals(endTs)) { endTime = currentTime; 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 index 26a625a..33629f0 100644 --- 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -27,8 +27,9 @@ 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 { + 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/DslContext.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslContext.java index cf7f51d..6088561 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,146 +19,146 @@ */ package org.onap.aai.rest.dsl; -import org.antlr.v4.runtime.ParserRuleContext; - import java.util.ArrayList; import java.util.Deque; import java.util.LinkedList; import java.util.List; +import org.antlr.v4.runtime.ParserRuleContext; + public class DslContext { - private ParserRuleContext ctx; - - private boolean validationFlag = true; - private boolean isStartNode = false; - private String startNode = ""; - private List<String> startNodeKeys = new ArrayList<>(); - - private String currentNode; - private String previousNode; - - private boolean isTraversal = false; - private boolean isWhereQuery = false; - private boolean isUnionQuery = false; - private boolean isUnionStart = false; - - private String whereStartNode = ""; - - private Deque<String> unionStartNodes = new LinkedList<>(); - - /* - * Limit Queries have to be applied in the end - so i have to set this in - * context - */ - public StringBuilder limitQuery = new StringBuilder(); - - public ParserRuleContext getCtx() { - return ctx; - } - - public void setCtx(ParserRuleContext ctx) { - 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<String> getStartNodeKeys() { - return startNodeKeys; - } - - public String getCurrentNode() { - return currentNode; - } - - public void setCurrentNode(String currentNode) { - this.currentNode = currentNode; - } - - public String getPreviousNode() { - return previousNode; - } - - public void setPreviousNode(String previousNode) { - this.previousNode = previousNode; - } - - public boolean isTraversal() { - return isTraversal; - } - - public void setTraversal(boolean isTraversal) { - this.isTraversal = isTraversal; - } - - public boolean isWhereQuery() { - return isWhereQuery; - } - - public void setWhereQuery(boolean isWhereQuery) { - this.isWhereQuery = isWhereQuery; - } - - public boolean isUnionQuery() { - return isUnionQuery; - } - - public void setUnionQuery(boolean isUnionQuery) { - this.isUnionQuery = isUnionQuery; - } - - public String getWhereStartNode() { - return whereStartNode; - } - - public void setWhereStartNode(String whereStartNode) { - this.whereStartNode = whereStartNode; - } - - public Deque<String> getUnionStartNodes() { - return unionStartNodes; - } - - public void setUnionStartNodes(Deque<String> unionStartNodes) { - this.unionStartNodes = unionStartNodes; - } - - public boolean isUnionStart() { - return isUnionStart; - } - - public void setUnionStart(boolean isUnionStart) { - this.isUnionStart = isUnionStart; - } - - public StringBuilder getLimitQuery() { - return limitQuery; - } - - public void setLimitQuery(StringBuilder limitQuery) { - this.limitQuery = limitQuery; - } - - public boolean isValidationFlag() { - return validationFlag; - } - - public void setValidationFlag(boolean validationFlag) { - this.validationFlag = validationFlag; - } + private ParserRuleContext ctx; + + private boolean validationFlag = true; + private boolean isStartNode = false; + private String startNode = ""; + private List<String> startNodeKeys = new ArrayList<>(); + + private String currentNode; + private String previousNode; + + private boolean isTraversal = false; + private boolean isWhereQuery = false; + private boolean isUnionQuery = false; + private boolean isUnionStart = false; + + private String whereStartNode = ""; + + private Deque<String> unionStartNodes = new LinkedList<>(); + + /* + * Limit Queries have to be applied in the end - so i have to set this in + * context + */ + public StringBuilder limitQuery = new StringBuilder(); + + public ParserRuleContext getCtx() { + return ctx; + } + + public void setCtx(ParserRuleContext ctx) { + 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<String> getStartNodeKeys() { + return startNodeKeys; + } + + public String getCurrentNode() { + return currentNode; + } + + public void setCurrentNode(String currentNode) { + this.currentNode = currentNode; + } + + public String getPreviousNode() { + return previousNode; + } + + public void setPreviousNode(String previousNode) { + this.previousNode = previousNode; + } + + public boolean isTraversal() { + return isTraversal; + } + + public void setTraversal(boolean isTraversal) { + this.isTraversal = isTraversal; + } + + public boolean isWhereQuery() { + return isWhereQuery; + } + + public void setWhereQuery(boolean isWhereQuery) { + this.isWhereQuery = isWhereQuery; + } + + public boolean isUnionQuery() { + return isUnionQuery; + } + + public void setUnionQuery(boolean isUnionQuery) { + this.isUnionQuery = isUnionQuery; + } + + public String getWhereStartNode() { + return whereStartNode; + } + + public void setWhereStartNode(String whereStartNode) { + this.whereStartNode = whereStartNode; + } + + public Deque<String> getUnionStartNodes() { + return unionStartNodes; + } + + public void setUnionStartNodes(Deque<String> unionStartNodes) { + this.unionStartNodes = unionStartNodes; + } + + public boolean isUnionStart() { + return isUnionStart; + } + + public void setUnionStart(boolean isUnionStart) { + this.isUnionStart = isUnionStart; + } + + public StringBuilder getLimitQuery() { + return limitQuery; + } + + 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/DslQueryBuilder.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/DslQueryBuilder.java index d5b365e..a953fcb 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -21,6 +21,13 @@ package org.onap.aai.rest.dsl; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; + +import java.util.List; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.edges.EdgeRule; import org.onap.aai.edges.EdgeRuleQuery; @@ -35,12 +42,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; -import java.util.List; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - public class DslQueryBuilder { private final EdgeIngestor edgeRules; @@ -84,7 +85,7 @@ public class DslQueryBuilder { */ public DslQueryBuilder end(long selectCounter) { selectCount = selectCounter; - if(selectCounter <= 0) { + if (selectCounter <= 0) { return this.end(); } else { query.append(".select('stepMain').fold().dedup()"); @@ -108,26 +109,28 @@ public class DslQueryBuilder { } public DslQueryBuilder edgeQuery(Edge edge, String aNode, String bNode) { - List<String> edgeLabels = edge.getLabels().stream().map(edgeLabel -> StringUtils.quote(edgeLabel.getLabel())).collect(Collectors.toList()); + List<String> edgeLabels = edge.getLabels().stream() + .map(edgeLabel -> StringUtils.quote(edgeLabel.getLabel())).collect(Collectors.toList()); EdgeRuleQuery.Builder baseQ = new EdgeRuleQuery.Builder(aNode, bNode); - if((AAIDirection.valueOf(edge.getDirection().name())) != AAIDirection.BOTH) { - baseQ = baseQ.direction(AAIDirection.valueOf(edge.getDirection().name())); + if ((AAIDirection.valueOf(edge.getDirection().name())) != AAIDirection.BOTH) { + baseQ = baseQ.direction(AAIDirection.valueOf(edge.getDirection().name())); } return edgeQueryWithBuilder(edgeLabels, aNode, bNode, baseQ); } - private DslQueryBuilder edgeQueryWithBuilder(List<String> edgeLabels, String aNode, String bNode, EdgeRuleQuery.Builder edgeBuilder) { - //TODO : change this for fuzzy search. + private DslQueryBuilder edgeQueryWithBuilder(List<String> edgeLabels, String aNode, + String bNode, EdgeRuleQuery.Builder edgeBuilder) { + // 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(", String.join(",", edgeLabels), "))"); + edgeLabelsClause = String.join("", ", new ArrayList<>(Arrays.asList(", + String.join(",", edgeLabels), "))"); } LOGGER.debug("EdgeLabels Clause: {}", edgeLabelsClause); @@ -140,23 +143,27 @@ public class DslQueryBuilder { try { rules.putAll(edgeRules.getRules(edgeBuilder.label(label).build())); } catch (EdgeRuleNotFoundException e) { - queryException.append("Exception while finding the edge rule between the nodeTypes: ").append(aNode).append(", ").append(bNode).append(label); + queryException + .append("Exception while finding the edge rule between the nodeTypes: ") + .append(aNode).append(", ").append(bNode).append(label); } }); } } catch (EdgeRuleNotFoundException e) { if (!edgeLabels.isEmpty()) { - queryException.append("- No EdgeRule found for passed nodeTypes: ").append(aNode).append(", ").append(bNode).append(edgeLabels.stream().toString()); - } - else { - queryException.append("- No EdgeRule found for passed nodeTypes: ").append(aNode).append(", ").append(bNode); + queryException.append("- No EdgeRule found for passed nodeTypes: ").append(aNode) + .append(", ").append(bNode).append(edgeLabels.stream().toString()); + } else { + queryException.append("- No EdgeRule found for passed nodeTypes: ").append(aNode) + .append(", ").append(bNode); } return this; } if (rules.isEmpty() || rules.keys().isEmpty()) { - queryException.append("- No EdgeRule found for passed nodeTypes: ").append(aNode).append(", ").append(bNode); + queryException.append("- No EdgeRule found for passed nodeTypes: ").append(aNode) + .append(", ").append(bNode); } else { if (edgeLabels.isEmpty()) { if (edgeRules.hasRule(edgeBuilder.edgeType(EdgeType.TREE).build())) { @@ -172,16 +179,15 @@ public class DslQueryBuilder { } } - query.append(edgeTraversalClause).append(edgeType).append(" '").append(aNode) - .append("','").append(bNode).append("'").append(edgeLabelsClause).append(")"); + query.append(edgeTraversalClause).append(edgeType).append(" '").append(aNode).append("','") + .append(bNode).append("'").append(edgeLabelsClause).append(")"); return this; } - public DslQueryBuilder where(boolean isNot) { query.append(".where("); - if(isNot){ + if (isNot) { query.append("builder.newInstance().not("); } return this; @@ -189,7 +195,7 @@ public class DslQueryBuilder { public DslQueryBuilder endWhere(boolean isNot) { query.append(")"); - if(isNot){ + if (isNot) { query.append(")"); } return this; @@ -201,13 +207,14 @@ public class DslQueryBuilder { } public DslQueryBuilder filter(boolean isNot, String node, String key, List<String> values) { - return this.filterPropertyStart(isNot,values).filterPropertyKeys(node, key, values).filterPropertyEnd(); + return this.filterPropertyStart(isNot, values).filterPropertyKeys(node, key, values) + .filterPropertyEnd(); } public DslQueryBuilder filterPropertyStart(boolean isNot, List<String> values) { if (isNot) { query.append(".getVerticesExcludeByProperty("); - } else if(values!= null && !values.isEmpty() && Boolean.parseBoolean(values.get(0))) { + } else if (values != null && !values.isEmpty() && Boolean.parseBoolean(values.get(0))) { query.append(".getVerticesByBooleanProperty("); } else { query.append(".getVerticesByProperty("); @@ -225,10 +232,8 @@ public class DslQueryBuilder { Introspector obj = loader.introspectorFromName(node); if (keys.isEmpty()) { - queryException.append("No keys sent. Valid keys for ") - .append(node) - .append(" are ") - .append(String.join(",", obj.getIndexedProperties())); + queryException.append("No keys sent. Valid keys for ").append(node).append(" are ") + .append(String.join(",", obj.getIndexedProperties())); return this; } @@ -241,21 +246,22 @@ public class DslQueryBuilder { public DslQueryBuilder select(long selectCounter, List<String> keys) { /* - * TODO : isNot should look at the vertex properties and include everything except the notKeys + * TODO : isNot should look at the vertex properties and include everything except the + * notKeys */ Pattern p = Pattern.compile("aai-node-type"); Matcher m = p.matcher(query); int count = 0; - while (m.find()){ + while (m.find()) { count++; } if (selectCounter == count || keys == null) { String selectStep = "step" + selectCounter; -// String keysArray = String.join(",", keys); - query.append(".as('").append(selectStep).append("')") - .append(".as('stepMain').select('").append(selectStep).append("')"); + // String keysArray = String.join(",", keys); + query.append(".as('").append(selectStep).append("')").append(".as('stepMain').select('") + .append(selectStep).append("')"); } return this; } @@ -263,7 +269,8 @@ public class DslQueryBuilder { public DslQueryBuilder filterPropertyKeys(String node, String key, List<String> values) { try { Introspector obj = loader.introspectorFromName(node); - Optional<String> alias = obj.getPropertyMetadata(key.replace("'",""), PropertyMetadata.DB_ALIAS); + Optional<String> alias = + obj.getPropertyMetadata(key.replace("'", ""), PropertyMetadata.DB_ALIAS); if (alias.isPresent()) { key = StringUtils.quote(alias.get()); } @@ -271,14 +278,15 @@ public class DslQueryBuilder { query.append(key); if (values != null && !values.isEmpty()) { - if (values.size() > 1) { // values.size() > 1 indicates possibility of a list + if (values.size() > 1) { // values.size() > 1 indicates possibility of a list // eliminate quotes from each element for (int i = 0; i < values.size(); i++) { values.set(i, getConvertedValue(classType, key, values.get(i))); } String valuesArray = String.join(",", values); - query.append(",").append(" new ArrayList<>(Arrays.asList(").append(valuesArray).append("))"); - } else { // otherwise values should only contain one value + query.append(",").append(" new ArrayList<>(Arrays.asList(").append(valuesArray) + .append("))"); + } else { // otherwise values should only contain one value query.append(",").append(getConvertedValue(classType, key, values.get(0))); } } @@ -297,30 +305,29 @@ public class DslQueryBuilder { if (classType.equals(Integer.class.getName())) { int castInt = Integer.parseInt(convertedValue); convertedValue = String.valueOf(castInt); - } - else if (classType.equals(Long.class.getName())) { + } else if (classType.equals(Long.class.getName())) { long castLong = Long.parseLong(convertedValue); convertedValue = String.valueOf(castLong); - } - else if (classType.equals(Boolean.class.getName())) { - if ("1".equals(convertedValue)) { // checking for integer true value + } else if (classType.equals(Boolean.class.getName())) { + if ("1".equals(convertedValue)) { // checking for integer true value convertedValue = "true"; } boolean castBoolean = Boolean.parseBoolean(convertedValue); convertedValue = String.valueOf(castBoolean); } } catch (Exception e) { - queryException.append("AAI_4020 ").append(String.format("Value [%s] is not an instance of the expected data type for property key [%s] and cannot be converted. " + - "Expected: class %s, found: class %s", value, key, classType, String.class.getName())); + queryException.append("AAI_4020 ").append(String.format( + "Value [%s] is not an instance of the expected data type for property key [%s] and cannot be converted. " + + "Expected: class %s, found: class %s", + value, key, classType, String.class.getName())); } } return convertedValue; } private boolean isTypeSensitive(String classType) { - if (classType.equals(Integer.class.getName()) || - classType.equals(Boolean.class.getName()) || - classType.equals(Long.class.getName())) { + if (classType.equals(Integer.class.getName()) || classType.equals(Boolean.class.getName()) + || classType.equals(Long.class.getName())) { return true; } return false; @@ -368,5 +375,4 @@ public class DslQueryBuilder { 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 14663e1..a21ca04 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,6 +19,15 @@ */ package org.onap.aai.rest.dsl; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.misc.ParseCancellationException; import org.antlr.v4.runtime.tree.ParseTree; @@ -32,138 +41,144 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - /** * The Class DslQueryProcessor. */ public class DslQueryProcessor { - private static final Logger LOGGER = LoggerFactory.getLogger(DslQueryProcessor.class); - - private Map<QueryVersion, ParseTreeListener> dslListeners; - private boolean startNodeValidationFlag = true; - private String validationRules = ""; - private String packageName = "org.onap.aai.dsl."; - private static final String LEXER = "AAIDslLexer"; - private static final String PARSER = "AAIDslParser"; - private static final String EOF_TOKEN = "<EOF>"; - - private boolean isAggregate = false; - - @Autowired - public DslQueryProcessor(Map<QueryVersion, ParseTreeListener> dslListeners) { - this.dslListeners = dslListeners; - } - - public Map<String, Object> parseAaiQuery(QueryVersion version, String aaiQuery) throws AAIException { - Map<String, Object> resultMap = new HashMap<>(); - try { - // Create a input stream that reads our string - InputStream stream = new ByteArrayInputStream(aaiQuery.getBytes(StandardCharsets.UTF_8)); - - packageName = packageName + version.toString().toLowerCase() + "."; - - Class<?> lexerClass = Class.forName(packageName + LEXER); - Class<?> parserClass = Class.forName(packageName + PARSER); - - Lexer lexer = (Lexer)lexerClass.getConstructor(CharStream.class).newInstance(CharStreams.fromStream(stream, StandardCharsets.UTF_8)); - lexer.removeErrorListeners(); - lexer.addErrorListener(new AAIDslErrorListener()); - CommonTokenStream tokens = new CommonTokenStream(lexer); - - // Parser that feeds off of the tokens buffer - Parser parser = (Parser)parserClass.getConstructor(TokenStream.class).newInstance(tokens); - parser.removeErrorListeners(); - parser.addErrorListener(new AAIDslErrorListener()); - ParseTreeListener dslListener = dslListeners.get(version); - dslListener.getClass().getMethod("setValidationFlag", boolean.class).invoke(dslListener, isStartNodeValidationFlag()); - dslListener.getClass().getMethod("setAggregateFlag", boolean.class).invoke(dslListener,isAggregate()); - - if(!getValidationRules().isEmpty() && !"none".equals(getValidationRules())) { - DslValidator validator = new DslValidator.Builder() - .create(); - dslListener.getClass().getMethod("setQueryValidator", DslValidator.class, String.class).invoke(dslListener, validator, getValidationRules()); - } - - // Specify our entry point - ParseTree ptree = (ParseTree)parserClass.getMethod("aaiquery").invoke(parser); - - // Check if there is no EOF token at the end of the parsed aaiQuery - // If none, DSL query may have not been parsed correctly and omitted part of the query out. If so error out. - // If it wasn't expecting a opening parens after a closing bracket for union, it will drop the proceeding part of the query. - Token eofToken = tokens.get(tokens.size() - 1); + private static final Logger LOGGER = LoggerFactory.getLogger(DslQueryProcessor.class); + + private Map<QueryVersion, ParseTreeListener> dslListeners; + private boolean startNodeValidationFlag = true; + private String validationRules = ""; + private String packageName = "org.onap.aai.dsl."; + private static final String LEXER = "AAIDslLexer"; + private static final String PARSER = "AAIDslParser"; + private static final String EOF_TOKEN = "<EOF>"; + + private boolean isAggregate = false; + + @Autowired + public DslQueryProcessor(Map<QueryVersion, ParseTreeListener> dslListeners) { + this.dslListeners = dslListeners; + } + + public Map<String, Object> parseAaiQuery(QueryVersion version, String aaiQuery) + throws AAIException { + Map<String, Object> resultMap = new HashMap<>(); + try { + // Create a input stream that reads our string + InputStream stream = + new ByteArrayInputStream(aaiQuery.getBytes(StandardCharsets.UTF_8)); + + packageName = packageName + version.toString().toLowerCase() + "."; + + Class<?> lexerClass = Class.forName(packageName + LEXER); + Class<?> parserClass = Class.forName(packageName + PARSER); + + Lexer lexer = (Lexer) lexerClass.getConstructor(CharStream.class) + .newInstance(CharStreams.fromStream(stream, StandardCharsets.UTF_8)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new AAIDslErrorListener()); + CommonTokenStream tokens = new CommonTokenStream(lexer); + + // Parser that feeds off of the tokens buffer + Parser parser = + (Parser) parserClass.getConstructor(TokenStream.class).newInstance(tokens); + parser.removeErrorListeners(); + parser.addErrorListener(new AAIDslErrorListener()); + ParseTreeListener dslListener = dslListeners.get(version); + dslListener.getClass().getMethod("setValidationFlag", boolean.class).invoke(dslListener, + isStartNodeValidationFlag()); + dslListener.getClass().getMethod("setAggregateFlag", boolean.class).invoke(dslListener, + isAggregate()); + + if (!getValidationRules().isEmpty() && !"none".equals(getValidationRules())) { + DslValidator validator = new DslValidator.Builder().create(); + dslListener.getClass() + .getMethod("setQueryValidator", DslValidator.class, String.class) + .invoke(dslListener, validator, getValidationRules()); + } + + // Specify our entry point + ParseTree ptree = (ParseTree) parserClass.getMethod("aaiquery").invoke(parser); + + // Check if there is no EOF token at the end of the parsed aaiQuery + // If none, DSL query may have not been parsed correctly and omitted part of the query + // out. If so error out. + // If it wasn't expecting a opening parens after a closing bracket for union, it will + // drop the proceeding part of the query. + Token eofToken = tokens.get(tokens.size() - 1); if (eofToken != null && !eofToken.getText().equals(EOF_TOKEN)) { - if (eofToken.getText().equals("(")) { - throw new AAIException("AAI_6153", "DSL Syntax Error while processing the query: DSL Query could not be parsed correctly. Please check your syntax."); - } - } - - if (LOGGER.isInfoEnabled()) { - LOGGER.info("QUERY-interim {}", ptree.toStringTree(parser)); - } - - // Walk it and attach our listener - ParseTreeWalker walker = new ParseTreeWalker(); - - walker.walk(dslListener, ptree); - String query = (String) dslListener.getClass().getMethod("getQuery").invoke(dslListener); - resultMap.put("query", query); - if (version.equals(QueryVersion.V2)){ - Map<String, List<String>> selectKeys= ((DslListener)dslListener).getSelectKeys(); - if (selectKeys != null && !selectKeys.isEmpty()){ - resultMap.put("propertiesMap", selectKeys); - } - } - LOGGER.info("Final QUERY {}", query); - return resultMap; - }catch(InvocationTargetException e){ - if (e.getTargetException() instanceof ParseCancellationException) { - throw new AAIException("AAI_6153", "DSL Syntax Error while processing the query :" + e.getTargetException().getMessage()); - } else if (e.getTargetException() instanceof AAIException) { - AAIException ex = (AAIException)e.getTargetException(); - throw new AAIException((ex.getCode().isEmpty() ? "AAI_6149":ex.getCode()), "DSL Error while processing the query :" + ex.getMessage()); - } else { - throw new AAIException("AAI_6152","Exception while processing DSL query"); - } - - } catch(ParseCancellationException e) { - throw new AAIException("AAI_6153", "DSL Syntax Error while processing the query: " + e.getMessage()); - - } catch (Exception e) { - throw new AAIException("AAI_6152","Error while processing the query: " + e.getMessage()); - - } - } - - public boolean isStartNodeValidationFlag() { - return startNodeValidationFlag; - } - - public void setStartNodeValidationFlag(boolean startNodeValidationFlag) { - this.startNodeValidationFlag = startNodeValidationFlag; - } - - public boolean isAggregate() { - return isAggregate; - } - - public void setAggregate(boolean aggregate) { - this.isAggregate = aggregate; - } - - public String getValidationRules() { - return validationRules; - } - - public void setValidationRules(String validationRules) { - this.validationRules = validationRules; - } + if (eofToken.getText().equals("(")) { + throw new AAIException("AAI_6153", + "DSL Syntax Error while processing the query: DSL Query could not be parsed correctly. Please check your syntax."); + } + } + + if (LOGGER.isInfoEnabled()) { + LOGGER.info("QUERY-interim {}", ptree.toStringTree(parser)); + } + + // Walk it and attach our listener + ParseTreeWalker walker = new ParseTreeWalker(); + + walker.walk(dslListener, ptree); + String query = + (String) dslListener.getClass().getMethod("getQuery").invoke(dslListener); + resultMap.put("query", query); + if (version.equals(QueryVersion.V2)) { + Map<String, List<String>> selectKeys = ((DslListener) dslListener).getSelectKeys(); + if (selectKeys != null && !selectKeys.isEmpty()) { + resultMap.put("propertiesMap", selectKeys); + } + } + LOGGER.info("Final QUERY {}", query); + return resultMap; + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof ParseCancellationException) { + throw new AAIException("AAI_6153", "DSL Syntax Error while processing the query :" + + e.getTargetException().getMessage()); + } else if (e.getTargetException() instanceof AAIException) { + AAIException ex = (AAIException) e.getTargetException(); + throw new AAIException((ex.getCode().isEmpty() ? "AAI_6149" : ex.getCode()), + "DSL Error while processing the query :" + ex.getMessage()); + } else { + throw new AAIException("AAI_6152", "Exception while processing DSL query"); + } + + } catch (ParseCancellationException e) { + throw new AAIException("AAI_6153", + "DSL Syntax Error while processing the query: " + e.getMessage()); + + } catch (Exception e) { + throw new AAIException("AAI_6152", + "Error while processing the query: " + e.getMessage()); + + } + } + + public boolean isStartNodeValidationFlag() { + return startNodeValidationFlag; + } + + public void setStartNodeValidationFlag(boolean startNodeValidationFlag) { + this.startNodeValidationFlag = startNodeValidationFlag; + } + + public boolean isAggregate() { + return isAggregate; + } + + public void setAggregate(boolean aggregate) { + this.isAggregate = aggregate; + } + + public String getValidationRules() { + return validationRules; + } + + public void setValidationRules(String validationRules) { + this.validationRules = validationRules; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/Edge.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/Edge.java index c3be5dc..111c188 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/Edge.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/Edge.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,17 +19,17 @@ */ package org.onap.aai.rest.dsl; -import org.onap.aai.rest.enums.EdgeDirection; - import java.util.List; import java.util.stream.Collectors; +import org.onap.aai.rest.enums.EdgeDirection; + public class Edge { private List<EdgeLabel> labels; private EdgeDirection direction; - public Edge (EdgeDirection direction, List<EdgeLabel> labels) { + public Edge(EdgeDirection direction, List<EdgeLabel> labels) { this.labels = labels; this.direction = direction; } @@ -53,7 +53,7 @@ public class Edge { @Override public String toString() { return String.format("labels: %s, direction: %s ", - labels.stream().map(EdgeLabel::getLabel).collect(Collectors.joining(",")), - this.getDirection().name()); + labels.stream().map(EdgeLabel::getLabel).collect(Collectors.joining(",")), + this.getDirection().name()); } -}
\ No newline at end of file +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/EdgeLabel.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/EdgeLabel.java index 703adaf..6acf758 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/EdgeLabel.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/EdgeLabel.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -24,7 +24,7 @@ public class EdgeLabel { private String label; private boolean isExactMatch; - public EdgeLabel (String label, boolean isExactMatch) { + public EdgeLabel(String label, boolean isExactMatch) { this.isExactMatch = isExactMatch; this.label = label; } @@ -45,4 +45,4 @@ public class EdgeLabel { this.isExactMatch = isExactMatch; } -}
\ No newline at end of file +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v1/DslListener.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v1/DslListener.java index 4bb093e..ad2899c 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v1/DslListener.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v1/DslListener.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,6 +20,11 @@ package org.onap.aai.rest.dsl.v1; import com.google.common.collect.Lists; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.onap.aai.dsl.v1.AAIDslBaseListener; import org.onap.aai.dsl.v1.AAIDslParser; import org.onap.aai.edges.EdgeIngestor; @@ -36,271 +41,274 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - /** * The Class DslListener. */ public class DslListener extends AAIDslBaseListener { - private static final Logger LOGGER = LoggerFactory.getLogger(DslListener.class); - - private boolean validationFlag = false; - private EdgeIngestor edgeIngestor; - private Loader loader; - private Optional<DslValidator> queryValidator = Optional.empty(); - private boolean hasReturnValue = false; - - private String validationRules = "none"; - - private Deque<DslQueryBuilder> dslQueryBuilders = new LinkedList<>(); - private Deque<String> traversedNodes = new LinkedList<>(); - private Deque<List<String>> returnedNodes = new LinkedList<>(); - - private List<String> traversedEdgeLabels = new LinkedList<>(); - - private boolean isAggregate = false; - - /* - * Additional datastructures to store all nodeCount & looped edges - */ - private int nodeCount = 0; - private List<String> traversedEdges = new LinkedList<>(); - - /** - * Instantiates a new DslListener. - */ - @Autowired - public DslListener(EdgeIngestor edgeIngestor, SchemaVersions schemaVersions, LoaderFactory loaderFactory) { - this.loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); - this.edgeIngestor = edgeIngestor; - } - - public DslQueryBuilder builder() { - return dslQueryBuilders.peekFirst(); - } - - public String getQuery() throws AAIException { - if (!getException().isEmpty()) { - AAIException aaiException = new AAIException("AAI_6149", getException()); - ErrorLogHelper.logException(aaiException); - throw aaiException; - } - - DslValidatorRule ruleValidator = new DslValidatorRule.Builder() - .loop(getValidationRules() , traversedEdges) - .nodeCount(getValidationRules(), nodeCount).build(); - if(queryValidator.isPresent() && !queryValidator.get().validate(ruleValidator)){ - AAIException aaiException = new AAIException("AAI_6151", "Validation error " + queryValidator.get().getErrorMessage() ); - ErrorLogHelper.logException(aaiException); - throw aaiException; - } - 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() { - List<String> exceptions = dslQueryBuilders.stream().map(dslQb -> dslQb.getQueryException().toString()).collect(Collectors.toList()); - return String.join("", Lists.reverse(exceptions)); - } - - @Override - public void enterAaiquery(AAIDslParser.AaiqueryContext ctx) { - dslQueryBuilders.push(new DslQueryBuilder(edgeIngestor, loader)); - } - - @Override - public void exitAaiquery(AAIDslParser.AaiqueryContext ctx) { - if (!hasReturnValue) { - throw new RuntimeException(new AAIException("AAI_6149", "No nodes marked for output")); - } - } - - @Override - public void enterStartStatement(AAIDslParser.StartStatementContext ctx) { - builder().start(); - } - - @Override - public void exitStartStatement(AAIDslParser.StartStatementContext ctx) { - builder().end(); - if (!traversedNodes.isEmpty()) { - traversedNodes.removeFirst(); - } - - } - - @Override - public void exitLimit(AAIDslParser.LimitContext ctx) { - builder().limit(ctx.num().getText()); - } - - @Override - public void enterNestedStatement(AAIDslParser.NestedStatementContext ctx) { - dslQueryBuilders.addFirst(new DslQueryBuilder(edgeIngestor, loader)); - builder().startInstance(); - } - - @Override - public void exitNestedStatement(AAIDslParser.NestedStatementContext ctx) { - int count = 1; - if(!ctx.traversal().isEmpty()) { - count += ctx.traversal().size() ; - } - String resultNode = traversedNodes.peekFirst(); - - 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(); - } - - @Override - public void enterVertex(AAIDslParser.VertexContext ctx) { - - if (!traversedNodes.isEmpty()) { - builder().edgeQuery(traversedEdgeLabels, traversedNodes.peekFirst(), ctx.label().getText()); - traversedEdges.add(traversedNodes.peekFirst() + ctx.label().getText()); - } else { - builder().nodeQuery(ctx.label().getText()); - } - - traversedNodes.addFirst(ctx.label().getText()); - } - - @Override - 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().replaceFirst("\'", "").substring(0, e.getText().length() - 2)).collect(Collectors.toList()); - - } - builder().validateFilter(ctx.label().getText(), allKeys); - } - if (ctx.store() != null) { - builder().store(); - hasReturnValue = true; - } - traversedEdgeLabels = new ArrayList<>(); - nodeCount++; - } - - - @Override - public void enterUnionVertex(AAIDslParser.UnionVertexContext ctx) { - returnedNodes.addFirst(new ArrayList<>()); - builder().union(); - } - - @Override - public void exitUnionVertex(AAIDslParser.UnionVertexContext ctx) { - String resultNode = returnedNodes.pop().get(0); - traversedNodes.addFirst(resultNode); - builder().endUnion(); - if (ctx.store() != null) { - builder().store(); - hasReturnValue = true; - } - } - - @Override - public void enterWhereFilter(AAIDslParser.WhereFilterContext ctx) { - boolean isNot = ctx.not() != null && !ctx.not().isEmpty(); - returnedNodes.addFirst(new ArrayList<>()); - builder().where(isNot); - } - - @Override - public void exitWhereFilter(AAIDslParser.WhereFilterContext ctx) { - if(!returnedNodes.isEmpty()) { - returnedNodes.pop(); - } - boolean isNot = ctx.not() != null && !ctx.not().isEmpty(); - builder().endWhere(isNot); - } - - @Override - public void enterEdgeFilter(AAIDslParser.EdgeFilterContext ctx) { - traversedEdgeLabels = ctx.key().stream().map(value -> value.getText()).collect(Collectors.toList()); - - } - - @Override - 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(); - - List<AAIDslParser.BoolContext> booleanValues = ctx.bool(); - - /* - * Add all String values - */ - List<String> values = valueList.stream().filter(value -> !filterKey.equals(value.getText())) - .map(value -> value.getText()).collect(Collectors.toList()); - - /* - * Add all numeric values - */ - values.addAll(numberValues.stream().filter(value -> !filterKey.equals(value.getText())) - .map(value -> value.getText()).collect(Collectors.toList())); - - /* - * Add all boolean values - */ - values.addAll(booleanValues.stream().filter(value -> !filterKey.equals(value.getText())) - .map(value -> value.getText().toLowerCase()).collect(Collectors.toList())); - - builder().filter(isNot, traversedNodes.peekFirst(), filterKey, values); - - } - - public boolean isValidationFlag() { - return validationFlag; - } - - public void setValidationFlag(boolean validationFlag) { - this.validationFlag = validationFlag; - } - - public void setQueryValidator(DslValidator queryValidator, String validationRules) { - this.queryValidator = Optional.of(queryValidator); - this.validationRules = validationRules; - } - public String getValidationRules() { - return validationRules; - } - - public void setAggregateFlag(boolean isAggregate) { - this.isAggregate = isAggregate; - } - - public boolean isAggregate(){ - return this.isAggregate; - } + private static final Logger LOGGER = LoggerFactory.getLogger(DslListener.class); + + private boolean validationFlag = false; + private EdgeIngestor edgeIngestor; + private Loader loader; + private Optional<DslValidator> queryValidator = Optional.empty(); + private boolean hasReturnValue = false; + + private String validationRules = "none"; + + private Deque<DslQueryBuilder> dslQueryBuilders = new LinkedList<>(); + private Deque<String> traversedNodes = new LinkedList<>(); + private Deque<List<String>> returnedNodes = new LinkedList<>(); + + private List<String> traversedEdgeLabels = new LinkedList<>(); + + private boolean isAggregate = false; + + /* + * Additional datastructures to store all nodeCount & looped edges + */ + private int nodeCount = 0; + private List<String> traversedEdges = new LinkedList<>(); + + /** + * Instantiates a new DslListener. + */ + @Autowired + public DslListener(EdgeIngestor edgeIngestor, SchemaVersions schemaVersions, + LoaderFactory loaderFactory) { + this.loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, + schemaVersions.getDefaultVersion()); + this.edgeIngestor = edgeIngestor; + } + + public DslQueryBuilder builder() { + return dslQueryBuilders.peekFirst(); + } + + public String getQuery() throws AAIException { + if (!getException().isEmpty()) { + AAIException aaiException = new AAIException("AAI_6149", getException()); + ErrorLogHelper.logException(aaiException); + throw aaiException; + } + + DslValidatorRule ruleValidator = + new DslValidatorRule.Builder().loop(getValidationRules(), traversedEdges) + .nodeCount(getValidationRules(), nodeCount).build(); + if (queryValidator.isPresent() && !queryValidator.get().validate(ruleValidator)) { + AAIException aaiException = new AAIException("AAI_6151", + "Validation error " + queryValidator.get().getErrorMessage()); + ErrorLogHelper.logException(aaiException); + throw aaiException; + } + 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() { + List<String> exceptions = dslQueryBuilders.stream() + .map(dslQb -> dslQb.getQueryException().toString()).collect(Collectors.toList()); + return String.join("", Lists.reverse(exceptions)); + } + + @Override + public void enterAaiquery(AAIDslParser.AaiqueryContext ctx) { + dslQueryBuilders.push(new DslQueryBuilder(edgeIngestor, loader)); + } + + @Override + public void exitAaiquery(AAIDslParser.AaiqueryContext ctx) { + if (!hasReturnValue) { + throw new RuntimeException(new AAIException("AAI_6149", "No nodes marked for output")); + } + } + + @Override + public void enterStartStatement(AAIDslParser.StartStatementContext ctx) { + builder().start(); + } + + @Override + public void exitStartStatement(AAIDslParser.StartStatementContext ctx) { + builder().end(); + if (!traversedNodes.isEmpty()) { + traversedNodes.removeFirst(); + } + + } + + @Override + public void exitLimit(AAIDslParser.LimitContext ctx) { + builder().limit(ctx.num().getText()); + } + + @Override + public void enterNestedStatement(AAIDslParser.NestedStatementContext ctx) { + dslQueryBuilders.addFirst(new DslQueryBuilder(edgeIngestor, loader)); + builder().startInstance(); + } + + @Override + public void exitNestedStatement(AAIDslParser.NestedStatementContext ctx) { + int count = 1; + if (!ctx.traversal().isEmpty()) { + count += ctx.traversal().size(); + } + String resultNode = traversedNodes.peekFirst(); + + 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(); + } + + @Override + public void enterVertex(AAIDslParser.VertexContext ctx) { + + if (!traversedNodes.isEmpty()) { + builder().edgeQuery(traversedEdgeLabels, traversedNodes.peekFirst(), + ctx.label().getText()); + traversedEdges.add(traversedNodes.peekFirst() + ctx.label().getText()); + } else { + builder().nodeQuery(ctx.label().getText()); + } + + traversedNodes.addFirst(ctx.label().getText()); + } + + @Override + 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().replaceFirst("\'", "").substring(0, e.getText().length() - 2)) + .collect(Collectors.toList()); + + } + builder().validateFilter(ctx.label().getText(), allKeys); + } + if (ctx.store() != null) { + builder().store(); + hasReturnValue = true; + } + traversedEdgeLabels = new ArrayList<>(); + nodeCount++; + } + + @Override + public void enterUnionVertex(AAIDslParser.UnionVertexContext ctx) { + returnedNodes.addFirst(new ArrayList<>()); + builder().union(); + } + + @Override + public void exitUnionVertex(AAIDslParser.UnionVertexContext ctx) { + String resultNode = returnedNodes.pop().get(0); + traversedNodes.addFirst(resultNode); + builder().endUnion(); + if (ctx.store() != null) { + builder().store(); + hasReturnValue = true; + } + } + + @Override + public void enterWhereFilter(AAIDslParser.WhereFilterContext ctx) { + boolean isNot = ctx.not() != null && !ctx.not().isEmpty(); + returnedNodes.addFirst(new ArrayList<>()); + builder().where(isNot); + } + + @Override + public void exitWhereFilter(AAIDslParser.WhereFilterContext ctx) { + if (!returnedNodes.isEmpty()) { + returnedNodes.pop(); + } + boolean isNot = ctx.not() != null && !ctx.not().isEmpty(); + builder().endWhere(isNot); + } + + @Override + public void enterEdgeFilter(AAIDslParser.EdgeFilterContext ctx) { + traversedEdgeLabels = + ctx.key().stream().map(value -> value.getText()).collect(Collectors.toList()); + + } + + @Override + 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(); + + List<AAIDslParser.BoolContext> booleanValues = ctx.bool(); + + /* + * Add all String values + */ + List<String> values = valueList.stream().filter(value -> !filterKey.equals(value.getText())) + .map(value -> value.getText()).collect(Collectors.toList()); + + /* + * Add all numeric values + */ + values.addAll(numberValues.stream().filter(value -> !filterKey.equals(value.getText())) + .map(value -> value.getText()).collect(Collectors.toList())); + + /* + * Add all boolean values + */ + values.addAll(booleanValues.stream().filter(value -> !filterKey.equals(value.getText())) + .map(value -> value.getText().toLowerCase()).collect(Collectors.toList())); + + builder().filter(isNot, traversedNodes.peekFirst(), filterKey, values); + + } + + public boolean isValidationFlag() { + return validationFlag; + } + + public void setValidationFlag(boolean validationFlag) { + this.validationFlag = validationFlag; + } + + public void setQueryValidator(DslValidator queryValidator, String validationRules) { + this.queryValidator = Optional.of(queryValidator); + this.validationRules = validationRules; + } + + public String getValidationRules() { + return validationRules; + } + + public void setAggregateFlag(boolean isAggregate) { + this.isAggregate = isAggregate; + } + + public boolean isAggregate() { + return this.isAggregate; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v2/DslListener.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v2/DslListener.java index 66ca8a1..7e46c0b 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v2/DslListener.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v2/DslListener.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,6 +20,11 @@ package org.onap.aai.rest.dsl.v2; import com.google.common.collect.Lists; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.onap.aai.dsl.v2.AAIDslBaseListener; import org.onap.aai.dsl.v2.AAIDslParser; import org.onap.aai.edges.EdgeIngestor; @@ -39,273 +44,274 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - /** * The Class DslListener. */ public class DslListener extends AAIDslBaseListener { - private static final Logger LOGGER = LoggerFactory.getLogger(DslListener.class.getName()); - - private boolean validationFlag = false; - private EdgeIngestor edgeIngestor; - private Loader loader; - private Optional<DslValidator> queryValidator = Optional.empty(); - private boolean hasReturnValue = false; - - private String validationRules = "none"; - - private Deque<DslQueryBuilder> dslQueryBuilders = new LinkedList<>(); - private Deque<String> traversedNodes = new LinkedList<>(); - private Deque<List<String>> returnedNodes = new LinkedList<>(); - - private Deque<Edge> traversedEdges = new ArrayDeque<>(); - private long selectCounter = 0; - - /* - * Additional datastructures to store all nodeCount & looped edges - */ - int nodeCount = 0; - private List<String> traversedEdgesOld = new LinkedList<>(); - - private Map<String, List<String>> selectKeys = new HashMap<String, List<String>>(); - private boolean isAggregate; - - public Map<String, List<String>> getSelectKeys() { - return selectKeys; - } - - public void setSelectKeys(String nodeType, List<String> properties) { - this.selectKeys.put(nodeType, properties); - } - - /** - * Instantiates a new DslListener. - */ - @Autowired - public DslListener(EdgeIngestor edgeIngestor, SchemaVersions schemaVersions, LoaderFactory loaderFactory) { - this.loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, schemaVersions.getDefaultVersion()); - this.edgeIngestor = edgeIngestor; - } - - public DslQueryBuilder builder() { - return dslQueryBuilders.peekFirst(); - } - - public String getQuery() throws AAIException { - //TODO Change the exception reporting - if (!getException().isEmpty()) { - AAIException aaiException = new AAIException("AAI_6149", getException()); - ErrorLogHelper.logException(aaiException); - throw aaiException; - } - - DslValidatorRule ruleValidator = new DslValidatorRule.Builder() - .loop(getValidationRules() , traversedEdgesOld) - .nodeCount(getValidationRules(), nodeCount).build(); - if(queryValidator.isPresent() && !queryValidator.get().validate(ruleValidator)){ - AAIException aaiException = new AAIException("AAI_6151", "Validation error " + queryValidator.get().getErrorMessage() ); - ErrorLogHelper.logException(aaiException); - throw aaiException; - } - 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() { - List<String> exceptions = dslQueryBuilders.stream().map(dslQb -> dslQb.getQueryException().toString()).collect(Collectors.toList()); - return String.join("", Lists.reverse(exceptions)); - } - - @Override - public void enterAaiquery(AAIDslParser.AaiqueryContext ctx) { - dslQueryBuilders.push(new DslQueryBuilder(edgeIngestor, loader)); - } - - @Override - public void exitAaiquery(AAIDslParser.AaiqueryContext ctx) { - if (!hasReturnValue) { - throw new RuntimeException(new AAIException("AAI_6149", "No nodes marked for output")); - } - } - - @Override - public void enterStartStatement(AAIDslParser.StartStatementContext ctx) { - builder().start(); - } - - @Override - public void exitStartStatement(AAIDslParser.StartStatementContext ctx) { - builder().end(selectCounter); - if (!traversedNodes.isEmpty()) { - traversedNodes.removeFirst(); - } - - } - - @Override - public void exitLimit(AAIDslParser.LimitContext ctx) { - builder().limit(ctx.num().getText()); - } - - @Override - public void enterNestedStatement(AAIDslParser.NestedStatementContext ctx) { - dslQueryBuilders.addFirst(new DslQueryBuilder(edgeIngestor, loader)); - builder().startInstance(); - } - - @Override - public void exitNestedStatement(AAIDslParser.NestedStatementContext ctx) { - int count = 1; - if(!ctx.traversal().isEmpty()) { - count = ctx.traversal().size() ; - } - String resultNode = traversedNodes.peekFirst(); - - 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(); - } - - @Override - public void enterVertex(AAIDslParser.VertexContext ctx) { - - if (!traversedEdges.isEmpty() && !traversedNodes.isEmpty()) { - builder().edgeQuery(traversedEdges.peekFirst(), traversedNodes.peekFirst(), ctx.label().getText()); - traversedEdgesOld.add(traversedNodes.peekFirst() + ctx.label().getText()); - } else { - builder().nodeQuery(ctx.label().getText()); - } - - traversedNodes.addFirst(ctx.label().getText()); - } - - @Override - 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().replaceFirst("\'", "").substring(0, e.getText().length() - 2)).collect(Collectors.toList()); - } - builder().validateFilter(ctx.label().getText(), allKeys); - } - if (ctx.store() != null) { - if (isAggregate()) { - builder().select(selectCounter++, null); - } - builder().store(); - hasReturnValue = true; - } - nodeCount++; - } - - - @Override - public void enterUnionVertex(AAIDslParser.UnionVertexContext ctx) { - returnedNodes.addFirst(new ArrayList<>()); - builder().union(); - } - - @Override - public void exitUnionVertex(AAIDslParser.UnionVertexContext ctx) { - String resultNode = returnedNodes.pop().get(0); - traversedNodes.addFirst(resultNode); - builder().endUnion(); - if (ctx.store() != null) { - builder().store(); - hasReturnValue = true; - } - } - - @Override - public void enterWhereFilter(AAIDslParser.WhereFilterContext ctx) { - boolean isNot = ctx.not() != null && !ctx.not().isEmpty(); - returnedNodes.addFirst(new ArrayList<>()); - builder().where(isNot); - } - - @Override - public void exitWhereFilter(AAIDslParser.WhereFilterContext ctx) { - if(!returnedNodes.isEmpty()) { - returnedNodes.pop(); - } - boolean isNot = ctx.not() != null && !ctx.not().isEmpty(); - builder().endWhere(isNot); - } - - @Override - public void enterEdge(AAIDslParser.EdgeContext ctx) { - List<EdgeLabel> labels = new ArrayList<>(); - - if(ctx.edgeFilter() != null) { - labels.addAll(ctx.edgeFilter().key().stream().map( - e -> new EdgeLabel(removeSingleQuotes(e.getText()), true)) - .collect(Collectors.toList())); - } - EdgeDirection direction = EdgeDirection.BOTH; - if(ctx.DIRTRAVERSE() != null){ - direction = EdgeDirection.fromValue(ctx.DIRTRAVERSE().getText()); - } - traversedEdges.addFirst(new Edge(direction, labels)); - } - - protected String removeSingleQuotes(String value) { - return value.replaceFirst("^'(.*)'$", "$1"); - } - - @Override - 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(); - - List<AAIDslParser.BoolContext> booleanValues = ctx.bool(); - - /* - * Add all String values - */ - List<String> values = valueList.stream().filter(value -> !filterKey.equals(value.getText())) - .map(value -> value.getText()).collect(Collectors.toList()); - /* - * Add all numeric values - */ - values.addAll(numberValues.stream().filter(value -> !filterKey.equals(value.getText())) - .map(value -> value.getText()).collect(Collectors.toList())); - - /* - * Add all boolean values - */ - values.addAll(booleanValues.stream().filter(value -> !filterKey.equals(value.getText())) - .map(value -> value.getText().toLowerCase()).collect(Collectors.toList())); - - builder().filter(isNot, traversedNodes.peekFirst(), filterKey, values); - - } + private static final Logger LOGGER = LoggerFactory.getLogger(DslListener.class.getName()); + + private boolean validationFlag = false; + private EdgeIngestor edgeIngestor; + private Loader loader; + private Optional<DslValidator> queryValidator = Optional.empty(); + private boolean hasReturnValue = false; + + private String validationRules = "none"; + + private Deque<DslQueryBuilder> dslQueryBuilders = new LinkedList<>(); + private Deque<String> traversedNodes = new LinkedList<>(); + private Deque<List<String>> returnedNodes = new LinkedList<>(); + + private Deque<Edge> traversedEdges = new ArrayDeque<>(); + private long selectCounter = 0; + + /* + * Additional datastructures to store all nodeCount & looped edges + */ + int nodeCount = 0; + private List<String> traversedEdgesOld = new LinkedList<>(); + + private Map<String, List<String>> selectKeys = new HashMap<String, List<String>>(); + private boolean isAggregate; + + public Map<String, List<String>> getSelectKeys() { + return selectKeys; + } + + public void setSelectKeys(String nodeType, List<String> properties) { + this.selectKeys.put(nodeType, properties); + } + + /** + * Instantiates a new DslListener. + */ + @Autowired + public DslListener(EdgeIngestor edgeIngestor, SchemaVersions schemaVersions, + LoaderFactory loaderFactory) { + this.loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, + schemaVersions.getDefaultVersion()); + this.edgeIngestor = edgeIngestor; + } + + public DslQueryBuilder builder() { + return dslQueryBuilders.peekFirst(); + } + + public String getQuery() throws AAIException { + // TODO Change the exception reporting + if (!getException().isEmpty()) { + AAIException aaiException = new AAIException("AAI_6149", getException()); + ErrorLogHelper.logException(aaiException); + throw aaiException; + } + + DslValidatorRule ruleValidator = + new DslValidatorRule.Builder().loop(getValidationRules(), traversedEdgesOld) + .nodeCount(getValidationRules(), nodeCount).build(); + if (queryValidator.isPresent() && !queryValidator.get().validate(ruleValidator)) { + AAIException aaiException = new AAIException("AAI_6151", + "Validation error " + queryValidator.get().getErrorMessage()); + ErrorLogHelper.logException(aaiException); + throw aaiException; + } + 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() { + List<String> exceptions = dslQueryBuilders.stream() + .map(dslQb -> dslQb.getQueryException().toString()).collect(Collectors.toList()); + return String.join("", Lists.reverse(exceptions)); + } + + @Override + public void enterAaiquery(AAIDslParser.AaiqueryContext ctx) { + dslQueryBuilders.push(new DslQueryBuilder(edgeIngestor, loader)); + } + + @Override + public void exitAaiquery(AAIDslParser.AaiqueryContext ctx) { + if (!hasReturnValue) { + throw new RuntimeException(new AAIException("AAI_6149", "No nodes marked for output")); + } + } + + @Override + public void enterStartStatement(AAIDslParser.StartStatementContext ctx) { + builder().start(); + } + + @Override + public void exitStartStatement(AAIDslParser.StartStatementContext ctx) { + builder().end(selectCounter); + if (!traversedNodes.isEmpty()) { + traversedNodes.removeFirst(); + } + + } + + @Override + public void exitLimit(AAIDslParser.LimitContext ctx) { + builder().limit(ctx.num().getText()); + } + + @Override + public void enterNestedStatement(AAIDslParser.NestedStatementContext ctx) { + dslQueryBuilders.addFirst(new DslQueryBuilder(edgeIngestor, loader)); + builder().startInstance(); + } + + @Override + public void exitNestedStatement(AAIDslParser.NestedStatementContext ctx) { + int count = 1; + if (!ctx.traversal().isEmpty()) { + count = ctx.traversal().size(); + } + String resultNode = traversedNodes.peekFirst(); + + 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(); + } + + @Override + public void enterVertex(AAIDslParser.VertexContext ctx) { + + if (!traversedEdges.isEmpty() && !traversedNodes.isEmpty()) { + builder().edgeQuery(traversedEdges.peekFirst(), traversedNodes.peekFirst(), + ctx.label().getText()); + traversedEdgesOld.add(traversedNodes.peekFirst() + ctx.label().getText()); + } else { + builder().nodeQuery(ctx.label().getText()); + } + + traversedNodes.addFirst(ctx.label().getText()); + } + + @Override + 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().replaceFirst("\'", "").substring(0, e.getText().length() - 2)) + .collect(Collectors.toList()); + } + builder().validateFilter(ctx.label().getText(), allKeys); + } + if (ctx.store() != null) { + if (isAggregate()) { + builder().select(selectCounter++, null); + } + builder().store(); + hasReturnValue = true; + } + nodeCount++; + } + + @Override + public void enterUnionVertex(AAIDslParser.UnionVertexContext ctx) { + returnedNodes.addFirst(new ArrayList<>()); + builder().union(); + } + + @Override + public void exitUnionVertex(AAIDslParser.UnionVertexContext ctx) { + String resultNode = returnedNodes.pop().get(0); + traversedNodes.addFirst(resultNode); + builder().endUnion(); + if (ctx.store() != null) { + builder().store(); + hasReturnValue = true; + } + } + + @Override + public void enterWhereFilter(AAIDslParser.WhereFilterContext ctx) { + boolean isNot = ctx.not() != null && !ctx.not().isEmpty(); + returnedNodes.addFirst(new ArrayList<>()); + builder().where(isNot); + } + + @Override + public void exitWhereFilter(AAIDslParser.WhereFilterContext ctx) { + if (!returnedNodes.isEmpty()) { + returnedNodes.pop(); + } + boolean isNot = ctx.not() != null && !ctx.not().isEmpty(); + builder().endWhere(isNot); + } + + @Override + public void enterEdge(AAIDslParser.EdgeContext ctx) { + List<EdgeLabel> labels = new ArrayList<>(); + + if (ctx.edgeFilter() != null) { + labels.addAll(ctx.edgeFilter().key().stream() + .map(e -> new EdgeLabel(removeSingleQuotes(e.getText()), true)) + .collect(Collectors.toList())); + } + EdgeDirection direction = EdgeDirection.BOTH; + if (ctx.DIRTRAVERSE() != null) { + direction = EdgeDirection.fromValue(ctx.DIRTRAVERSE().getText()); + } + traversedEdges.addFirst(new Edge(direction, labels)); + } + + protected String removeSingleQuotes(String value) { + return value.replaceFirst("^'(.*)'$", "$1"); + } + + @Override + 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(); + + List<AAIDslParser.BoolContext> booleanValues = ctx.bool(); + + /* + * Add all String values + */ + List<String> values = valueList.stream().filter(value -> !filterKey.equals(value.getText())) + .map(value -> value.getText()).collect(Collectors.toList()); + /* + * Add all numeric values + */ + values.addAll(numberValues.stream().filter(value -> !filterKey.equals(value.getText())) + .map(value -> value.getText()).collect(Collectors.toList())); + + /* + * Add all boolean values + */ + values.addAll(booleanValues.stream().filter(value -> !filterKey.equals(value.getText())) + .map(value -> value.getText().toLowerCase()).collect(Collectors.toList())); + + builder().filter(isNot, traversedNodes.peekFirst(), filterKey, values); + + } @Override public void enterSelectFilter(AAIDslParser.SelectFilterContext ctx) { @@ -315,37 +321,40 @@ public class DslListener extends AAIDslBaseListener { /* * Add all String values */ - List<String> allKeys = keyList.stream().map(keyValue -> "'" + keyValue.getText().replace("'", "") + "'").collect(Collectors.toList()); - if (allKeys != null && !allKeys.isEmpty()){ - setSelectKeys(traversedNodes.getFirst(), allKeys); - } - if (isAggregate() && (traversedNodes.size() == nodeCount)) { - builder().select(selectCounter++, allKeys); - } + List<String> allKeys = + keyList.stream().map(keyValue -> "'" + keyValue.getText().replace("'", "") + "'") + .collect(Collectors.toList()); + if (allKeys != null && !allKeys.isEmpty()) { + setSelectKeys(traversedNodes.getFirst(), allKeys); + } + if (isAggregate() && (traversedNodes.size() == nodeCount)) { + builder().select(selectCounter++, allKeys); + } + } + + public boolean isValidationFlag() { + return validationFlag; } - public boolean isValidationFlag() { - return validationFlag; - } - - public void setValidationFlag(boolean validationFlag) { - this.validationFlag = validationFlag; - } - - public void setAggregateFlag(boolean isAggregate) { - this.isAggregate = isAggregate; - } - - public boolean isAggregate(){ - return this.isAggregate; - } - - public void setQueryValidator(DslValidator queryValidator, String validationRules) { - this.queryValidator = Optional.of(queryValidator); - this.validationRules = validationRules; - } - public String getValidationRules() { - return validationRules; - } + public void setValidationFlag(boolean validationFlag) { + this.validationFlag = validationFlag; + } + + public void setAggregateFlag(boolean isAggregate) { + this.isAggregate = isAggregate; + } + + public boolean isAggregate() { + return this.isAggregate; + } + + public void setQueryValidator(DslValidator queryValidator, String validationRules) { + this.queryValidator = Optional.of(queryValidator); + this.validationRules = validationRules; + } + + public String getValidationRules() { + return validationRules; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslQueryValidator.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslQueryValidator.java index 53f2c72..e82cfc2 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslQueryValidator.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslQueryValidator.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,13 +19,13 @@ */ package org.onap.aai.rest.dsl.validation; -import org.onap.aai.util.AAIConfig; -import org.onap.aai.util.TraversalConstants; - import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import org.onap.aai.util.AAIConfig; +import org.onap.aai.util.TraversalConstants; + public class DslQueryValidator extends DslValidator { protected DslQueryValidator(Builder builder) { @@ -34,7 +34,9 @@ public class DslQueryValidator extends DslValidator { public boolean validate(DslValidatorRule dslValidatorRule) { - return validateLoop(dslValidatorRule.isValidateLoop(), dslValidatorRule.getEdges()) && validateNodeCount(dslValidatorRule.isValidateNodeCount(), dslValidatorRule.getNodeCount()); + return validateLoop(dslValidatorRule.isValidateLoop(), dslValidatorRule.getEdges()) + && validateNodeCount(dslValidatorRule.isValidateNodeCount(), + dslValidatorRule.getNodeCount()); } private boolean validateLoop(boolean isValidateLoop, List<String> edges) { @@ -50,7 +52,8 @@ public class DslQueryValidator extends DslValidator { } private boolean validateNodeCount(boolean isValidateNodeCount, int nodeCount) { - String maxNodeString = AAIConfig.get("aai.dsl.max.nodecount", TraversalConstants.DSL_MAX_NODE_COUNT); + String maxNodeString = + AAIConfig.get("aai.dsl.max.nodecount", TraversalConstants.DSL_MAX_NODE_COUNT); int maxNodeCount = Integer.parseInt(maxNodeString); if (isValidateNodeCount && nodeCount > maxNodeCount) { this.errorMessage.append("NodeCount Validation failed"); diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslSchemaValidator.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslSchemaValidator.java index 54a2feb..15d8cca 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslSchemaValidator.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslSchemaValidator.java @@ -8,7 +8,7 @@ * 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 + * 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, diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslValidator.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslValidator.java index 128f8a8..7f14458 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslValidator.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslValidator.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -24,7 +24,6 @@ import org.onap.aai.exceptions.AAIException; public abstract class DslValidator { protected StringBuilder errorMessage = new StringBuilder(""); - protected DslValidator(DslValidator.Builder builder) { } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslValidatorRule.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslValidatorRule.java index 54d45bd..117c9a5 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslValidatorRule.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/validation/DslValidatorRule.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -84,7 +84,7 @@ public class DslValidatorRule { public static class Builder { - //todo optional + // todo optional String query = ""; boolean validateLoop = false; boolean validateNodeCount = false; @@ -114,7 +114,8 @@ public class DslValidatorRule { } public Builder nodeCount(String validateNodeCount, int nodeCount) { - if (validateNodeCount.contains(NODECOUNT_RULE) || validateNodeCount.contains(ALL_RULE)) { + if (validateNodeCount.contains(NODECOUNT_RULE) + || validateNodeCount.contains(ALL_RULE)) { this.setValidateNodeCount(true); this.nodeCount = nodeCount; } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/enums/EdgeDirection.java b/aai-traversal/src/main/java/org/onap/aai/rest/enums/EdgeDirection.java index 61f35ac..8aa7a69 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/enums/EdgeDirection.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/enums/EdgeDirection.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,10 +20,7 @@ package org.onap.aai.rest.enums; public enum EdgeDirection { - OUT(">>"), - IN("<<"), - BOTH(">"); - + OUT(">>"), IN("<<"), BOTH(">"); private final String value; @@ -31,7 +28,6 @@ public enum EdgeDirection { this.value = value; } - public static EdgeDirection fromValue(String value) { for (EdgeDirection d : values()) { @@ -41,8 +37,9 @@ public enum EdgeDirection { } return BOTH; } + @Override public String toString() { return value; } -}
\ No newline at end of file +} diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/enums/QueryVersion.java b/aai-traversal/src/main/java/org/onap/aai/rest/enums/QueryVersion.java index 0e30f28..8ba2faf 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/enums/QueryVersion.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/enums/QueryVersion.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,6 +20,5 @@ package org.onap.aai.rest.enums; public enum QueryVersion { - V1, - V2; -}
\ No newline at end of file + V1, V2; +} 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 index d17fb2b..e6f55eb 100644 --- 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -22,7 +22,7 @@ package org.onap.aai.rest.search; public abstract class CQConfig { protected GetCustomQueryConfig queryConfig; - public GetCustomQueryConfig getCustomQueryConfig(){ + public GetCustomQueryConfig getCustomQueryConfig() { return queryConfig; } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryConfig.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryConfig.java index 2fa7ec1..a7633ca 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryConfig.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryConfig.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -22,32 +22,35 @@ package org.onap.aai.rest.search; import java.util.List; public class CustomQueryConfig { - public CustomQueryConfig() { - // used by GetCustomQueryConfig - } - - - private String query; - private List<String> queryOptionalProperties; - private List<String> queryRequiredProperties; - - 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; - } + public CustomQueryConfig() { + // used by GetCustomQueryConfig + } + + private String query; + private List<String> queryOptionalProperties; + private List<String> queryRequiredProperties; + + 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/CustomQueryConfigDTO.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryConfigDTO.java index 30d8d30..7f90566 100644 --- 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -39,32 +39,32 @@ package org.onap.aai.rest.search; * ============LICENSE_END========================================================= */ -import org.springframework.util.StringUtils; - import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.util.StringUtils; + public class CustomQueryConfigDTO { - @JsonProperty("stored-query") - private String storedQuery; - @JsonProperty("query") - private CustomQueryDTO queryDTO; + @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 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 setQueryDTO(CustomQueryDTO query) { - this.queryDTO = query; - } + public void setStoredQuery(String storedQuery) { + this.storedQuery = storedQuery; + } - 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 index 16b1430..970e5b3 100644 --- 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 @@ -10,7 +10,7 @@ package org.onap.aai.rest.search; * 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 + * 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, @@ -20,37 +20,41 @@ package org.onap.aai.rest.search; * ============LICENSE_END========================================================= */ -import java.util.List; - import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.Lists; +import java.util.List; + 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; - } + 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 index cdc9d15..b64f07f 100644 --- 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -39,83 +39,79 @@ package org.onap.aai.rest.search; * ============LICENSE_END========================================================= */ +import com.beust.jcommander.internal.Maps; +import com.fasterxml.jackson.annotation.JsonProperty; + 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; - } - - + + @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 index 9c4c3b0..cda93fb 100644 --- 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,20 +20,20 @@ package org.onap.aai.rest.search; -import java.util.List; - import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + public class ExpectedResultsDto { - @JsonProperty("ids") - List<String> ids; + @JsonProperty("ids") + List<String> ids; + + public List<String> getIds() { + return ids; + } - public List<String> getIds() { - return ids; - } + public void setIds(List<String> ids) { + this.ids = ids; + } - public void setIds(List<String> ids) { - this.ids = ids; - } - } 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 8e62900..d63b910 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,9 +19,17 @@ */ package org.onap.aai.rest.search; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.att.eelf.configuration.EELFManager; + +import java.io.FileNotFoundException; +import java.net.URI; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; + import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; @@ -39,422 +47,431 @@ import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.serialization.queryformats.Format; import org.onap.aai.serialization.queryformats.SubGraphStyle; - -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.core.MultivaluedMap; -import java.io.FileNotFoundException; -import java.net.URI; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class GenericQueryProcessor { - private static Logger LOGGER = LoggerFactory.getLogger(GenericQueryProcessor.class); - - protected final Optional<URI> uri; - protected final MultivaluedMap<String, String> queryParams; - protected final Optional<Collection<Vertex>> vertices; - protected static Pattern p = Pattern.compile("query/(.*+)"); - protected Optional<String> gremlin; - protected final TransactionalGraphEngine dbEngine; - protected GremlinServerSingleton gremlinServerSingleton; - protected GroovyQueryBuilder groovyQueryBuilder = new GroovyQueryBuilder(); - protected final boolean isGremlin; - protected Optional<DslQueryProcessor> dslQueryProcessorOptional; - - public Map<String, List<String>> getPropertiesMap() { - return propertiesList; - } - - public void setPropertiesMap(Map<String, List<String>> propertiesMap) { - this.propertiesList = propertiesMap; - } - - private Map<String, List<String>> propertiesList; - /* dsl parameters to store dsl query and to check - - * if this is a DSL request - */ - protected Optional<String> dsl; - protected final boolean isDsl ; - protected boolean isHistory; - protected GraphTraversalSource traversalSource; - protected QueryStyle style; - protected QueryVersion dslApiVersion; - protected Format format; - - protected GenericQueryProcessor(Builder builder) { - this.uri = builder.getUri(); - this.dbEngine = builder.getDbEngine(); - this.vertices = builder.getVertices(); - this.gremlin = builder.getGremlin(); - this.isGremlin = builder.isGremlin(); - this.dsl = builder.getDsl(); - this.isDsl = builder.isDsl(); - this.gremlinServerSingleton = builder.getGremlinServerSingleton(); - this.dslQueryProcessorOptional = builder.getDslQueryProcessor(); - this.dslApiVersion = builder.getDslApiVersion(); - - if (uri.isPresent()) { - queryParams = URITools.getQueryMap(uri.get()); - } else if (builder.getUriParams() != null) { - queryParams = builder.getUriParams(); - } else { - queryParams = new MultivaluedHashMap<>(); - } - this.traversalSource = builder.getTraversalSource(); - this.style = builder.getStyle(); - this.isHistory = builder.isHistory(); - this.format = builder.getFormat(); - } - - protected abstract GraphTraversal<?,?> runQuery(String query, Map<String, Object> params, GraphTraversalSource traversalSource); - - protected List<Object> processSubGraph(SubGraphStyle style, GraphTraversal<?,?> g) { - final List<Object> resultVertices = new Vector<>(); - g.store("y"); - - if (SubGraphStyle.prune.equals(style) || SubGraphStyle.star.equals(style)) { - g.barrier().bothE(); - if (SubGraphStyle.prune.equals(style)) { - g.where(__.otherV().where(P.within("y"))); - } - g.dedup().subgraph("subGraph").cap("subGraph").map(x -> (Graph)x.get()).next().traversal().V().forEachRemaining(x -> { - resultVertices.add(x); - }); - } else { - resultVertices.addAll(g.toList()); - } - return resultVertices; - } - - public List<Object> execute(SubGraphStyle style) throws FileNotFoundException, AAIException { - final List<Object> resultVertices; - - Pair<String, Map<String, Object>> tuple = this.createQuery(); - String query = tuple.getValue0(); - if (queryParams.containsKey("as-tree")) { - if (queryParams.getFirst("as-tree").equalsIgnoreCase("true")) { - if (this.isDsl) { // If dsl query and as-tree parameter is true, remove "end" concatenation and append tree. - query = removeDslQueryEnd(query); - } - query = query.concat(".tree()"); // Otherwise, normal gremlin query will just append tree - } - } - Map<String, Object> params = tuple.getValue1(); - - if (query.equals("") && (vertices.isPresent() && vertices.get().isEmpty())) { - //nothing to do, just exit - return new ArrayList<>(); - } - GraphTraversal<?,?> g = this.runQuery(query, params, traversalSource); - - resultVertices = this.processSubGraph(style, g); - - return resultVertices; - } - - private String removeDslQueryEnd(String query) { - String end = ".cap('x').unfold().dedup()"; - if (query.length() <= end.length()) { - return query; - } - if (query.contains(end)) { - int startIndex = query.length() - end.length(); - for (int i = 0; startIndex - i >= 0; i++) { // remove tailing instance - startIndex = query.length() - end.length() - i; - int lastIndex = query.length() - i; - if (query.substring(startIndex, lastIndex).equals(end)) { - query = query.substring(0, startIndex) + query.substring(lastIndex); - break; - } - } - } - return query; - } - - protected Pair<String, Map<String, Object>> createQuery() throws AAIException { - Map<String, Object> params = new HashMap<>(); - String query = ""; - if (this.isGremlin) { - query = gremlin.get(); - - }else if (this.isDsl) { - String dslUserQuery = dsl.get(); - if(dslQueryProcessorOptional.isPresent()){ - Map<String, Object>resultMap = dslQueryProcessorOptional.get().parseAaiQuery(dslApiVersion, dslUserQuery); - String dslQuery = resultMap.get("query").toString(); - Object propMap = resultMap.get("propertiesMap"); - if (propMap instanceof Map) { - Map<String, List<String>> newPropMap = new HashMap<String, List<String>>(); - newPropMap = (Map<String, List<String>>)propMap; - setPropertiesMap(newPropMap); - } - query = groovyQueryBuilder.executeTraversal(dbEngine, dslQuery, params, style, traversalSource); - String startPrefix = "g.V()"; - query = startPrefix + query; - } - LOGGER.debug("Converted to gremlin query\n {}", query); - }else { - Matcher m = p.matcher(uri.get().getPath()); - String queryName = ""; - List<String> optionalParameters = Collections.emptyList(); - if (m.find()) { - queryName = m.group(1); - CustomQueryConfig queryConfig = gremlinServerSingleton.getCustomQueryConfig(queryName); - if ( queryConfig != null ) { - query = queryConfig.getQuery(); - optionalParameters = queryConfig.getQueryOptionalProperties(); - } - } - - for (String key : queryParams.keySet()) { - params.put(key, queryParams.getFirst(key)); - if ( optionalParameters.contains(key) ){ - optionalParameters.remove(key); - } - } - - if (!optionalParameters.isEmpty()){ - MissingOptionalParameter missingParameter = MissingOptionalParameter.getInstance(); - for ( String key : optionalParameters ) { - params.put(key, missingParameter); - } - } - - if (vertices.isPresent() && !vertices.get().isEmpty()) { - - // Get the vertices and convert them into object array - // The reason for this was .V() takes in an array of objects - // not a list of objects so that needs to be converted + private static Logger LOGGER = LoggerFactory.getLogger(GenericQueryProcessor.class); + + protected final Optional<URI> uri; + protected final MultivaluedMap<String, String> queryParams; + protected final Optional<Collection<Vertex>> vertices; + protected static Pattern p = Pattern.compile("query/(.*+)"); + protected Optional<String> gremlin; + protected final TransactionalGraphEngine dbEngine; + protected GremlinServerSingleton gremlinServerSingleton; + protected GroovyQueryBuilder groovyQueryBuilder = new GroovyQueryBuilder(); + protected final boolean isGremlin; + protected Optional<DslQueryProcessor> dslQueryProcessorOptional; + + public Map<String, List<String>> getPropertiesMap() { + return propertiesList; + } + + public void setPropertiesMap(Map<String, List<String>> propertiesMap) { + this.propertiesList = propertiesMap; + } + + private Map<String, List<String>> propertiesList; + /* + * dsl parameters to store dsl query and to check + * + * if this is a DSL request + */ + protected Optional<String> dsl; + protected final boolean isDsl; + protected boolean isHistory; + protected GraphTraversalSource traversalSource; + protected QueryStyle style; + protected QueryVersion dslApiVersion; + protected Format format; + + protected GenericQueryProcessor(Builder builder) { + this.uri = builder.getUri(); + this.dbEngine = builder.getDbEngine(); + this.vertices = builder.getVertices(); + this.gremlin = builder.getGremlin(); + this.isGremlin = builder.isGremlin(); + this.dsl = builder.getDsl(); + this.isDsl = builder.isDsl(); + this.gremlinServerSingleton = builder.getGremlinServerSingleton(); + this.dslQueryProcessorOptional = builder.getDslQueryProcessor(); + this.dslApiVersion = builder.getDslApiVersion(); + + if (uri.isPresent()) { + queryParams = URITools.getQueryMap(uri.get()); + } else if (builder.getUriParams() != null) { + queryParams = builder.getUriParams(); + } else { + queryParams = new MultivaluedHashMap<>(); + } + this.traversalSource = builder.getTraversalSource(); + this.style = builder.getStyle(); + this.isHistory = builder.isHistory(); + this.format = builder.getFormat(); + } + + protected abstract GraphTraversal<?, ?> runQuery(String query, Map<String, Object> params, + GraphTraversalSource traversalSource); + + protected List<Object> processSubGraph(SubGraphStyle style, GraphTraversal<?, ?> g) { + final List<Object> resultVertices = new Vector<>(); + g.store("y"); + + if (SubGraphStyle.prune.equals(style) || SubGraphStyle.star.equals(style)) { + g.barrier().bothE(); + if (SubGraphStyle.prune.equals(style)) { + g.where(__.otherV().where(P.within("y"))); + } + g.dedup().subgraph("subGraph").cap("subGraph").map(x -> (Graph) x.get()).next() + .traversal().V().forEachRemaining(x -> { + resultVertices.add(x); + }); + } else { + resultVertices.addAll(g.toList()); + } + return resultVertices; + } + + public List<Object> execute(SubGraphStyle style) throws FileNotFoundException, AAIException { + final List<Object> resultVertices; + + Pair<String, Map<String, Object>> tuple = this.createQuery(); + String query = tuple.getValue0(); + if (queryParams.containsKey("as-tree")) { + if (queryParams.getFirst("as-tree").equalsIgnoreCase("true")) { + if (this.isDsl) { // If dsl query and as-tree parameter is true, remove "end" + // concatenation and append tree. + query = removeDslQueryEnd(query); + } + query = query.concat(".tree()"); // Otherwise, normal gremlin query will just append + // tree + } + } + Map<String, Object> params = tuple.getValue1(); + + if (query.equals("") && (vertices.isPresent() && vertices.get().isEmpty())) { + // nothing to do, just exit + return new ArrayList<>(); + } + GraphTraversal<?, ?> g = this.runQuery(query, params, traversalSource); + + resultVertices = this.processSubGraph(style, g); + + return resultVertices; + } + + private String removeDslQueryEnd(String query) { + String end = ".cap('x').unfold().dedup()"; + if (query.length() <= end.length()) { + return query; + } + if (query.contains(end)) { + int startIndex = query.length() - end.length(); + for (int i = 0; startIndex - i >= 0; i++) { // remove tailing instance + startIndex = query.length() - end.length() - i; + int lastIndex = query.length() - i; + if (query.substring(startIndex, lastIndex).equals(end)) { + query = query.substring(0, startIndex) + query.substring(lastIndex); + break; + } + } + } + return query; + } + + protected Pair<String, Map<String, Object>> createQuery() throws AAIException { + Map<String, Object> params = new HashMap<>(); + String query = ""; + if (this.isGremlin) { + query = gremlin.get(); + + } else if (this.isDsl) { + String dslUserQuery = dsl.get(); + if (dslQueryProcessorOptional.isPresent()) { + Map<String, Object> resultMap = + dslQueryProcessorOptional.get().parseAaiQuery(dslApiVersion, dslUserQuery); + String dslQuery = resultMap.get("query").toString(); + Object propMap = resultMap.get("propertiesMap"); + if (propMap instanceof Map) { + Map<String, List<String>> newPropMap = new HashMap<String, List<String>>(); + newPropMap = (Map<String, List<String>>) propMap; + setPropertiesMap(newPropMap); + } + query = groovyQueryBuilder.executeTraversal(dbEngine, dslQuery, params, style, + traversalSource); + String startPrefix = "g.V()"; + query = startPrefix + query; + } + LOGGER.debug("Converted to gremlin query\n {}", query); + } else { + Matcher m = p.matcher(uri.get().getPath()); + String queryName = ""; + List<String> optionalParameters = Collections.emptyList(); + if (m.find()) { + queryName = m.group(1); + CustomQueryConfig queryConfig = + gremlinServerSingleton.getCustomQueryConfig(queryName); + if (queryConfig != null) { + query = queryConfig.getQuery(); + optionalParameters = queryConfig.getQueryOptionalProperties(); + } + } + + for (String key : queryParams.keySet()) { + params.put(key, queryParams.getFirst(key)); + if (optionalParameters.contains(key)) { + optionalParameters.remove(key); + } + } + + if (!optionalParameters.isEmpty()) { + MissingOptionalParameter missingParameter = MissingOptionalParameter.getInstance(); + for (String key : optionalParameters) { + params.put(key, missingParameter); + } + } + + if (vertices.isPresent() && !vertices.get().isEmpty()) { + + // Get the vertices and convert them into object array + // The reason for this was .V() takes in an array of objects + // not a list of objects so that needs to be converted // Also instead of statically creating the list which is a bad practice - // We are binding the array dynamically to the groovy processor correctly - // This will fix the memory issue of the method size too big - // as statically creating a list string and passing is not appropriate + // We are binding the array dynamically to the groovy processor correctly + // This will fix the memory issue of the method size too big + // as statically creating a list string and passing is not appropriate - Object [] startVertices = vertices.get().toArray(); + Object[] startVertices = vertices.get().toArray(); - params.put("startVertexes", startVertices); + params.put("startVertexes", startVertices); - if (query == null) { - query = ""; - } else { - query = groovyQueryBuilder.executeTraversal(dbEngine, query, params, style, traversalSource); - } + if (query == null) { + query = ""; + } else { + query = groovyQueryBuilder.executeTraversal(dbEngine, query, params, style, + traversalSource); + } - String startPrefix = "g.V(startVertexes)"; + String startPrefix = "g.V(startVertexes)"; - if (!"".equals(query)) { - query = startPrefix + query; - } else { - query = startPrefix; - } + if (!"".equals(query)) { + query = startPrefix + query; + } else { + query = startPrefix; + } - // Getting all the vertices and logging them is not reasonable - // As it could have performance impacts so doing a check here - // to see if the logger is trace so only print the start vertexes - // otherwise we would like to see what the gremlin query that was converted + // Getting all the vertices and logging them is not reasonable + // As it could have performance impacts so doing a check here + // to see if the logger is trace so only print the start vertexes + // otherwise we would like to see what the gremlin query that was converted // So to check if the output matches the desired behavior - // This way if to enable deeper logging, just changing logback would work - if(LOGGER.isTraceEnabled()){ - String readQuery = query.replaceAll("startVertexes", - Arrays.toString(startVertices).replaceAll("[^0-9,]", "")); - LOGGER.trace("Converted to gremlin query including the start vertices \n {}", readQuery); - } - else if(LOGGER.isDebugEnabled()){ - LOGGER.debug("Converted to gremlin query without the start vertices \n {}", query); - } - } else { - throw new AAIException("AAI_6148"); - } - - } - - return new Pair<>(query, params); - } - - public static class Builder { - - private final TransactionalGraphEngine dbEngine; - private Optional<URI> uri = Optional.empty(); - private Optional<String> gremlin = Optional.empty(); - private boolean isGremlin = false; - private Optional<Collection<Vertex>> vertices = Optional.empty(); - private QueryProcessorType processorType = QueryProcessorType.GREMLIN_SERVER; - - private Optional<String> dsl = Optional.empty(); - private boolean isDsl = false; - private DslQueryProcessor dslQueryProcessor; - private GremlinServerSingleton gremlinServerSingleton; - private Optional<String> nodeType = Optional.empty(); - private boolean isNodeTypeQuery = false; - protected MultivaluedMap<String, String> uriParams; - protected GraphTraversalSource traversalSource; - protected boolean isHistory = false; - protected QueryVersion dslApiVersion; - protected Format format; - - - protected QueryStyle style = QueryStyle.GREMLIN_TRAVERSAL; - - public Builder(TransactionalGraphEngine dbEngine, GremlinServerSingleton gremlinServerSingleton) { - this.dbEngine = dbEngine; - this.gremlinServerSingleton = gremlinServerSingleton; - } - - public Builder queryFrom(URI uri) { - this.uri = Optional.of(uri); - this.isGremlin = false; - return this; - } - - public Builder startFrom(Collection<Vertex> vertices) { - this.vertices = Optional.of(vertices); - return this; - } - - public Builder queryFrom( String query, String queryType) { - - if(queryType.equals("gremlin")){ - this.gremlin = Optional.of(query); - this.isGremlin = true; - } - if(queryType.equals("dsl")){ - this.dsl = Optional.of(query); - this.isDsl = true; - } - if(queryType.equals("nodeQuery")){ - this.nodeType = Optional.of(query); - this.isNodeTypeQuery = true; - } - return this; - } - - public Builder uriParams(MultivaluedMap<String, String> uriParams) { - this.uriParams = uriParams; - return this; - } - - public Builder processWith(QueryProcessorType type) { - this.processorType = type; - return this; - } - - public Builder format(Format format) { - this.format = format; - return this; - } - - public Builder traversalSource(boolean isHistory, GraphTraversalSource source) { - this.traversalSource = source; - this.isHistory = isHistory; - if(this.isHistory){ - this.style = QueryStyle.HISTORY_GREMLIN_TRAVERSAL; - } - - return this; - } - - public Builder queryProcessor(DslQueryProcessor dslQueryProcessor){ - this.dslQueryProcessor = dslQueryProcessor; - return this; - } - - public Builder version(QueryVersion version){ - this.dslApiVersion = version; - return this; - } - - public Optional<DslQueryProcessor> getDslQueryProcessor(){ - return Optional.ofNullable(this.dslQueryProcessor); - } - public TransactionalGraphEngine getDbEngine() { - return dbEngine; - } - - public Optional<URI> getUri() { - return uri; - } - - public MultivaluedMap<String, String> getUriParams() { return uriParams; } - - public Optional<String> getGremlin() { - return gremlin; - } - - public boolean isGremlin() { - return isGremlin; - } - - public Optional<String> getDsl() { - return dsl; - } - - public boolean isDsl() { - return isDsl; - } - - public Optional<Collection<Vertex>> getVertices() { - return vertices; - } - - public QueryProcessorType getProcessorType() { - return processorType; - } - - public GremlinServerSingleton getGremlinServerSingleton(){ - return gremlinServerSingleton; - } - - public Optional<String> getNodeType() { - return nodeType; - } - - public boolean isNodeTypeQuery() { - return isNodeTypeQuery; - } - - public GenericQueryProcessor create() { - if (isNodeTypeQuery()) { - return new NodeQueryProcessor(this); - } - return new GroovyShellImpl(this); - } - - public GraphTraversalSource getTraversalSource() { - return traversalSource; - } - - public void setTraversalSource(GraphTraversalSource traversalSource) { - this.traversalSource = traversalSource; - } - - public boolean isHistory() { - return isHistory; - } - - public void setHistory(boolean history) { - isHistory = history; - } - - public QueryStyle getStyle() { - return style; - } - - public void setStyle(QueryStyle style) { - this.style = style; - } - - public QueryVersion getDslApiVersion() { - return dslApiVersion; - } - - public void setDslApiVersion(QueryVersion dslApiVersion) { - this.dslApiVersion = dslApiVersion; - } - - public Format getFormat(){ return this.format; } - - } + // This way if to enable deeper logging, just changing logback would work + if (LOGGER.isTraceEnabled()) { + String readQuery = query.replaceAll("startVertexes", + Arrays.toString(startVertices).replaceAll("[^0-9,]", "")); + LOGGER.trace("Converted to gremlin query including the start vertices \n {}", + readQuery); + } else if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Converted to gremlin query without the start vertices \n {}", + query); + } + } else { + throw new AAIException("AAI_6148"); + } + + } + + return new Pair<>(query, params); + } + + public static class Builder { + + private final TransactionalGraphEngine dbEngine; + private Optional<URI> uri = Optional.empty(); + private Optional<String> gremlin = Optional.empty(); + private boolean isGremlin = false; + private Optional<Collection<Vertex>> vertices = Optional.empty(); + private QueryProcessorType processorType = QueryProcessorType.GREMLIN_SERVER; + + private Optional<String> dsl = Optional.empty(); + private boolean isDsl = false; + private DslQueryProcessor dslQueryProcessor; + private GremlinServerSingleton gremlinServerSingleton; + private Optional<String> nodeType = Optional.empty(); + private boolean isNodeTypeQuery = false; + protected MultivaluedMap<String, String> uriParams; + protected GraphTraversalSource traversalSource; + protected boolean isHistory = false; + protected QueryVersion dslApiVersion; + protected Format format; + + protected QueryStyle style = QueryStyle.GREMLIN_TRAVERSAL; + + public Builder(TransactionalGraphEngine dbEngine, + GremlinServerSingleton gremlinServerSingleton) { + this.dbEngine = dbEngine; + this.gremlinServerSingleton = gremlinServerSingleton; + } + + public Builder queryFrom(URI uri) { + this.uri = Optional.of(uri); + this.isGremlin = false; + return this; + } + + public Builder startFrom(Collection<Vertex> vertices) { + this.vertices = Optional.of(vertices); + return this; + } + + public Builder queryFrom(String query, String queryType) { + + if (queryType.equals("gremlin")) { + this.gremlin = Optional.of(query); + this.isGremlin = true; + } + if (queryType.equals("dsl")) { + this.dsl = Optional.of(query); + this.isDsl = true; + } + if (queryType.equals("nodeQuery")) { + this.nodeType = Optional.of(query); + this.isNodeTypeQuery = true; + } + return this; + } + + public Builder uriParams(MultivaluedMap<String, String> uriParams) { + this.uriParams = uriParams; + return this; + } + + public Builder processWith(QueryProcessorType type) { + this.processorType = type; + return this; + } + + public Builder format(Format format) { + this.format = format; + return this; + } + + public Builder traversalSource(boolean isHistory, GraphTraversalSource source) { + this.traversalSource = source; + this.isHistory = isHistory; + if (this.isHistory) { + this.style = QueryStyle.HISTORY_GREMLIN_TRAVERSAL; + } + + return this; + } + + public Builder queryProcessor(DslQueryProcessor dslQueryProcessor) { + this.dslQueryProcessor = dslQueryProcessor; + return this; + } + + public Builder version(QueryVersion version) { + this.dslApiVersion = version; + return this; + } + + public Optional<DslQueryProcessor> getDslQueryProcessor() { + return Optional.ofNullable(this.dslQueryProcessor); + } + + public TransactionalGraphEngine getDbEngine() { + return dbEngine; + } + + public Optional<URI> getUri() { + return uri; + } + + public MultivaluedMap<String, String> getUriParams() { + return uriParams; + } + + public Optional<String> getGremlin() { + return gremlin; + } + + public boolean isGremlin() { + return isGremlin; + } + + public Optional<String> getDsl() { + return dsl; + } + + public boolean isDsl() { + return isDsl; + } + + public Optional<Collection<Vertex>> getVertices() { + return vertices; + } + + public QueryProcessorType getProcessorType() { + return processorType; + } + + public GremlinServerSingleton getGremlinServerSingleton() { + return gremlinServerSingleton; + } + + public Optional<String> getNodeType() { + return nodeType; + } + + public boolean isNodeTypeQuery() { + return isNodeTypeQuery; + } + + public GenericQueryProcessor create() { + if (isNodeTypeQuery()) { + return new NodeQueryProcessor(this); + } + return new GroovyShellImpl(this); + } + + public GraphTraversalSource getTraversalSource() { + return traversalSource; + } + + public void setTraversalSource(GraphTraversalSource traversalSource) { + this.traversalSource = traversalSource; + } + + public boolean isHistory() { + return isHistory; + } + + public void setHistory(boolean history) { + isHistory = history; + } + + public QueryStyle getStyle() { + return style; + } + + public void setStyle(QueryStyle style) { + this.style = style; + } + + public QueryVersion getDslApiVersion() { + return dslApiVersion; + } + + public void setDslApiVersion(QueryVersion dslApiVersion) { + this.dslApiVersion = dslApiVersion; + } + + public Format getFormat() { + return this.format; + } + + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/GetCustomQueryConfig.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/GetCustomQueryConfig.java index 76ecd20..98eb551 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/search/GetCustomQueryConfig.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/GetCustomQueryConfig.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,11 +19,6 @@ */ package org.onap.aai.rest.search; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; - - import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -31,108 +26,108 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + public class GetCustomQueryConfig { - private JsonArray storedQueries = null; - private CustomQueryConfig customQueryConfig; - - - private static final String QUERY_CONFIG = "query"; - private static final String REQUIRED_CONFIG = "required-properties"; - private static final String OPTIONAL_CONFIG = "optional-properties"; - private static final String STORED_QUERIES_CONFIG = "stored-queries"; - private static final String STORED_QUERY_CONFIG = "stored-query"; - - public GetCustomQueryConfig(String customQueryJson ) { - init(customQueryJson); - } - - private void init( String customQueryJson) { - JsonParser parser = new JsonParser(); - JsonObject queriesObject = parser.parse(customQueryJson).getAsJsonObject(); - if (queriesObject.has(STORED_QUERIES_CONFIG)) { - - storedQueries = queriesObject.getAsJsonArray(STORED_QUERIES_CONFIG); - } - } - - private List<String> toStringList(JsonArray array) { - Gson converter = new Gson(); - Type listType = new TypeToken<List<String>>() {}.getType(); - return converter.fromJson(array, listType); - } - - private List<String> getPropertyList(JsonObject configObject, String config ) { - JsonElement subqueryConfig; - JsonArray props; - - if ( configObject.has(config)) { - subqueryConfig = configObject.get(config); - if ( subqueryConfig != null && !subqueryConfig.isJsonNull() ) { - props = subqueryConfig.getAsJsonArray(); - if ( props != null ) { - return toStringList(props); - } - } - } - return toStringList(null); - } - - private void getStoredQueryBlock( JsonObject configObject, String config ) { - if ( !configObject.has(config)) { - customQueryConfig.setQueryRequiredProperties( new ArrayList<>() ); - customQueryConfig.setQueryOptionalProperties( new ArrayList<>() ); - return; - } - - JsonElement queryConfig; - JsonObject subObject; - List<String> propertyList; - - queryConfig = configObject.get(config); - subObject = queryConfig.getAsJsonObject(); - propertyList = getPropertyList(subObject, REQUIRED_CONFIG); - if ( propertyList == null ) { - propertyList = new ArrayList<>(); - } - customQueryConfig.setQueryRequiredProperties( propertyList ); - propertyList = getPropertyList(subObject, OPTIONAL_CONFIG); - if ( propertyList == null ) { - propertyList = new ArrayList<>(); - } - customQueryConfig.setQueryOptionalProperties( propertyList ); - - } - - - public CustomQueryConfig getStoredQuery(String queryName ) { - - customQueryConfig = null; - JsonObject configObject; - JsonElement query; - JsonElement queryConfig; - - for (JsonElement storedQuery : storedQueries) { - if (storedQuery.isJsonObject()) { - JsonObject queryObject = storedQuery.getAsJsonObject(); - query = queryObject.get(queryName); - if ( query != null ) { - customQueryConfig = new CustomQueryConfig(); - configObject = query.getAsJsonObject(); - getStoredQueryBlock(configObject, QUERY_CONFIG); - if ( configObject.has(STORED_QUERY_CONFIG)) { - queryConfig = configObject.get(STORED_QUERY_CONFIG); - customQueryConfig.setQuery(queryConfig.getAsString()); - } - break; - } - } - } - - return customQueryConfig; - - } + private JsonArray storedQueries = null; + private CustomQueryConfig customQueryConfig; + + private static final String QUERY_CONFIG = "query"; + private static final String REQUIRED_CONFIG = "required-properties"; + private static final String OPTIONAL_CONFIG = "optional-properties"; + private static final String STORED_QUERIES_CONFIG = "stored-queries"; + private static final String STORED_QUERY_CONFIG = "stored-query"; + + public GetCustomQueryConfig(String customQueryJson) { + init(customQueryJson); + } + + private void init(String customQueryJson) { + JsonParser parser = new JsonParser(); + JsonObject queriesObject = parser.parse(customQueryJson).getAsJsonObject(); + if (queriesObject.has(STORED_QUERIES_CONFIG)) { + + storedQueries = queriesObject.getAsJsonArray(STORED_QUERIES_CONFIG); + } + } + + private List<String> toStringList(JsonArray array) { + Gson converter = new Gson(); + Type listType = new TypeToken<List<String>>() {}.getType(); + return converter.fromJson(array, listType); + } + + private List<String> getPropertyList(JsonObject configObject, String config) { + JsonElement subqueryConfig; + JsonArray props; + + if (configObject.has(config)) { + subqueryConfig = configObject.get(config); + if (subqueryConfig != null && !subqueryConfig.isJsonNull()) { + props = subqueryConfig.getAsJsonArray(); + if (props != null) { + return toStringList(props); + } + } + } + return toStringList(null); + } + + private void getStoredQueryBlock(JsonObject configObject, String config) { + if (!configObject.has(config)) { + customQueryConfig.setQueryRequiredProperties(new ArrayList<>()); + customQueryConfig.setQueryOptionalProperties(new ArrayList<>()); + return; + } + + JsonElement queryConfig; + JsonObject subObject; + List<String> propertyList; + + queryConfig = configObject.get(config); + subObject = queryConfig.getAsJsonObject(); + propertyList = getPropertyList(subObject, REQUIRED_CONFIG); + if (propertyList == null) { + propertyList = new ArrayList<>(); + } + customQueryConfig.setQueryRequiredProperties(propertyList); + propertyList = getPropertyList(subObject, OPTIONAL_CONFIG); + if (propertyList == null) { + propertyList = new ArrayList<>(); + } + customQueryConfig.setQueryOptionalProperties(propertyList); + + } + + public CustomQueryConfig getStoredQuery(String queryName) { + + customQueryConfig = null; + JsonObject configObject; + JsonElement query; + JsonElement queryConfig; + + for (JsonElement storedQuery : storedQueries) { + if (storedQuery.isJsonObject()) { + JsonObject queryObject = storedQuery.getAsJsonObject(); + query = queryObject.get(queryName); + if (query != null) { + customQueryConfig = new CustomQueryConfig(); + configObject = query.getAsJsonObject(); + getStoredQueryBlock(configObject, QUERY_CONFIG); + if (configObject.has(STORED_QUERY_CONFIG)) { + queryConfig = configObject.get(STORED_QUERY_CONFIG); + customQueryConfig.setQuery(queryConfig.getAsString()); + } + break; + } + } + } + return customQueryConfig; + } } 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 e30f13f..a3bb074 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,16 +19,8 @@ */ package org.onap.aai.rest.search; -import org.onap.aai.logging.LogFormatTools; -import org.onap.aai.util.AAIConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; 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; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -41,6 +33,16 @@ import java.util.Properties; import java.util.Timer; import java.util.TimerTask; +import javax.annotation.PostConstruct; + +import org.apache.tinkerpop.gremlin.driver.Cluster; +import org.onap.aai.logging.LogFormatTools; +import org.onap.aai.util.AAIConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + public class GremlinServerSingleton { private static Logger logger = LoggerFactory.getLogger(GremlinServerSingleton.class); @@ -48,8 +50,8 @@ public class GremlinServerSingleton { private boolean timerSet; private Timer timer; - CQConfig customQueryInfo; + /** * Initializes the gremlin server singleton * Loads the configuration of the gremlin server and creates a cluster @@ -60,29 +62,29 @@ public class GremlinServerSingleton { * */ @Autowired - public GremlinServerSingleton(CQConfig customQueryInfo){ - this.customQueryInfo = customQueryInfo; + public GremlinServerSingleton(CQConfig customQueryInfo) { + this.customQueryInfo = customQueryInfo; } /** * Gets the query using CustomQueryConfig + * * @param key * @return */ - public String getStoredQueryFromConfig(String key){ + public String getStoredQueryFromConfig(String key) { GetCustomQueryConfig queryConfig = customQueryInfo.getCustomQueryConfig(); - CustomQueryConfig customQueryConfig = queryConfig.getStoredQuery(key); - if ( customQueryConfig == null ) { - return null; - } - return customQueryConfig.getQuery(); + CustomQueryConfig customQueryConfig = queryConfig.getStoredQuery(key); + if (customQueryConfig == null) { + return null; + } + return customQueryConfig.getQuery(); } - + public CustomQueryConfig getCustomQueryConfig(String key) { GetCustomQueryConfig queryConfig = customQueryInfo.getCustomQueryConfig(); - return queryConfig.getStoredQuery(key); + 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 340c525..126d754 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -21,36 +21,35 @@ package org.onap.aai.rest.search; import java.util.Map; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import javax.ws.rs.core.MultivaluedHashMap; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.onap.aai.aailog.logs.AaiDBTraversalMetricLog; import org.onap.aai.restcore.search.GremlinGroovyShell; import org.onap.aai.restcore.util.URITools; import org.onap.aai.util.AAIConstants; -import javax.ws.rs.core.MultivaluedHashMap; - public class GroovyShellImpl extends GenericQueryProcessor { - protected GroovyShellImpl(Builder builder) { - super(builder); - } - - @Override - protected GraphTraversal<?,?> runQuery(String query, Map<String, Object> params, GraphTraversalSource traversalSource) { + protected GroovyShellImpl(Builder builder) { + super(builder); + } - AaiDBTraversalMetricLog metricLog = new AaiDBTraversalMetricLog (AAIConstants.AAI_TRAVERSAL_MS); - metricLog.pre(uri); + @Override + protected GraphTraversal<?, ?> runQuery(String query, Map<String, Object> params, + GraphTraversalSource traversalSource) { - params.put("g", traversalSource); - GremlinGroovyShell shell = new GremlinGroovyShell(); - GraphTraversal<?,?> graphTraversal = shell.executeTraversal(query, params); + AaiDBTraversalMetricLog metricLog = + new AaiDBTraversalMetricLog(AAIConstants.AAI_TRAVERSAL_MS); + metricLog.pre(uri); - metricLog.post(); - return graphTraversal; - } - -} + params.put("g", traversalSource); + GremlinGroovyShell shell = new GremlinGroovyShell(); + GraphTraversal<?, ?> graphTraversal = shell.executeTraversal(query, params); + metricLog.post(); + return graphTraversal; + } +} 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 index 42d88af..ebf49d7 100644 --- 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,16 +19,8 @@ */ package org.onap.aai.rest.search; -import org.onap.aai.exceptions.AAIException; -import org.onap.aai.logging.ErrorLogHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.att.eelf.configuration.EELFManager; -import org.onap.aai.logging.LogFormatTools; -import org.onap.aai.util.AAIConstants; -import org.springframework.beans.factory.annotation.Value; -import javax.annotation.PostConstruct; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -38,6 +30,16 @@ import java.util.Date; import java.util.Timer; import java.util.TimerTask; +import javax.annotation.PostConstruct; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.logging.ErrorLogHelper; +import org.onap.aai.logging.LogFormatTools; +import org.onap.aai.util.AAIConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; + public class LocalCQConfig extends CQConfig { private static Logger logger = LoggerFactory.getLogger(LocalCQConfig.class); @@ -51,7 +53,8 @@ public class LocalCQConfig extends CQConfig { public void init() { try { - String filepath = storedQueriesLocation + AAIConstants.AAI_FILESEP + "stored-queries.json"; + 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)); @@ -60,7 +63,8 @@ public class LocalCQConfig extends CQConfig { } catch (IOException e) { AAIException aaiException = new AAIException("AAI_4002", e); ErrorLogHelper.logException(aaiException); - //logger.error("Error occurred during the processing of query json file: " + LogFormatTools.getStackTop(e)); + // logger.error("Error occurred during the processing of query json file: " + + // LogFormatTools.getStackTop(e)); } TimerTask task = new FileWatcher(new File(storedQueriesLocation)) { @@ -75,7 +79,8 @@ public class LocalCQConfig extends CQConfig { } catch (IOException e) { AAIException aaiException = new AAIException("AAI_4002", e); ErrorLogHelper.logException(aaiException); - //logger.error("Error occurred during the processing of query json file: " + LogFormatTools.getStackTop(e)); + // logger.error("Error occurred during the processing of query json file: " + + // LogFormatTools.getStackTop(e)); } } }; diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/ModelAndNamedQueryRestProvider.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/ModelAndNamedQueryRestProvider.java index 821cb09..5c8b055 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/search/ModelAndNamedQueryRestProvider.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/ModelAndNamedQueryRestProvider.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,12 +19,23 @@ */ package org.onap.aai.rest.search; +import java.net.URI; +import java.util.ArrayList; +import java.util.Optional; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; + import org.onap.aai.aailog.logs.AaiDBTraversalMetricLog; import org.onap.aai.concurrent.AaiCallable; import org.onap.aai.dbgraphmap.SearchGraph; import org.onap.aai.exceptions.AAIException; import org.onap.aai.logging.ErrorLogHelper; - import org.onap.aai.rest.util.AAIExtensionMap; import org.onap.aai.restcore.HttpMethod; import org.onap.aai.restcore.RESTAPI; @@ -35,17 +46,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; -import java.net.URI; -import java.util.ArrayList; -import java.util.Optional; - /** * Implements the search subdomain in the REST API. All API calls must include * X-FromAppId and X-TransactionId in the header. @@ -54,213 +54,199 @@ import java.util.Optional; @Path("/search") public class ModelAndNamedQueryRestProvider extends RESTAPI { - private static final Logger LOGGER = LoggerFactory.getLogger(ModelAndNamedQueryRestProvider.class); - - public static final String NAMED_QUERY = "/named-query"; - - public static final String MODEL_QUERY = "/model"; - - - private SearchGraph searchGraph; - - private SchemaVersions schemaVersions; - - @Autowired - public ModelAndNamedQueryRestProvider(SearchGraph searchGraph, SchemaVersions schemaVersions){ - this.searchGraph = searchGraph; - this.schemaVersions = schemaVersions; - } - - /** - * Gets the named query response. - * - * @param headers the headers - * @param req the req - * @param queryParameters the query parameters - * @return the named query response - */ - /* ---------------- Start Named Query --------------------- */ - @POST - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Path(NAMED_QUERY) - public Response getNamedQueryResponse(@Context HttpHeaders headers, - @Context HttpServletRequest req, - String queryParameters, - @Context UriInfo info) { - return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, - TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, - TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, - headers, - info, - HttpMethod.GET, - new AaiCallable<Response>() { - @Override - public Response process() { - return processNamedQueryResponse(headers, req, queryParameters); - } - } - ); - } - - public Response processNamedQueryResponse(@Context HttpHeaders headers, - @Context HttpServletRequest req, - String queryParameters) { - AAIException ex = null; - Response response; - String fromAppId; - String transId; - - ArrayList<String> templateVars = new ArrayList<>(); - try { - fromAppId = getFromAppId(headers); - transId = getTransId(headers); - - AAIExtensionMap aaiExtMap = new AAIExtensionMap(); - aaiExtMap.setHttpHeaders(headers); - aaiExtMap.setServletRequest(req); - aaiExtMap.setApiVersion(schemaVersions.getDefaultVersion().toString()); - //only consider header value for search - - - AaiDBTraversalMetricLog metricLog = new AaiDBTraversalMetricLog (AAIConstants.AAI_TRAVERSAL_MS); - String uriString = req.getRequestURI(); - Optional<URI> o; - if (uriString != null) { - o = Optional.of(new URI(uriString)); - } - else { - o = Optional.empty(); - } - metricLog.pre(o); - - response = searchGraph.runNamedQuery(fromAppId, transId, queryParameters, aaiExtMap); - metricLog.post(); - - } catch (AAIException e) { - // send error response - ex = e; - templateVars.add("POST Search"); - templateVars.add("getNamedQueryResponse"); - response = Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) - .build(); - } catch (Exception e) { - // send error response - ex = new AAIException("AAI_4000", e); - templateVars.add("POST Search"); - templateVars.add("getNamedQueryResponse"); - response = Response - .status(Status.INTERNAL_SERVER_ERROR) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); - } finally { - // log success or failure - if (ex != null) { - ErrorLogHelper.logException(ex); - } - } - return response; - } - - /** - * Gets the model query response. - * - * @param headers the headers - * @param req the req - * @param inboundPayload the inbound payload - * @param action the action - * @return the model query response - */ - /* ---------------- Start Named Query --------------------- */ - @POST - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Path(MODEL_QUERY) - public Response getModelQueryResponse(@Context HttpHeaders headers, - @Context HttpServletRequest req, - String inboundPayload, - @QueryParam("action") String action, - @Context UriInfo info) { - return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, - TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, - TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, - headers, - info, - HttpMethod.GET, - new AaiCallable<Response>() { - @Override - public Response process() { - return processModelQueryResponse(headers, req, inboundPayload, action); - } - } - ); - } - - public Response processModelQueryResponse(@Context HttpHeaders headers, - @Context HttpServletRequest req, - String inboundPayload, - @QueryParam("action") String action) { - AAIException ex = null; - Response response; - String fromAppId; - String transId; - ArrayList<String> templateVars = new ArrayList<>(); - try { - fromAppId = getFromAppId(headers); - transId = getTransId(headers); - - AAIExtensionMap aaiExtMap = new AAIExtensionMap(); - aaiExtMap.setHttpHeaders(headers); - aaiExtMap.setServletRequest(req); - aaiExtMap.setApiVersion(schemaVersions.getDefaultVersion().toString()); - aaiExtMap.setFromAppId(fromAppId); - aaiExtMap.setTransId(transId); - - //only consider header value for search - - - AaiDBTraversalMetricLog metricLog = new AaiDBTraversalMetricLog (AAIConstants.AAI_TRAVERSAL_MS); - String uriString = req.getRequestURI(); - Optional<URI> o; - if (uriString != null) { - o = Optional.of(new URI(uriString)); - } - else { - o = Optional.empty(); - } - metricLog.pre(o); - if (action != null && action.equalsIgnoreCase("DELETE")) { - response = searchGraph.executeModelOperation(fromAppId, transId, inboundPayload, true, aaiExtMap); - } else { - response = searchGraph.executeModelOperation(fromAppId, transId, inboundPayload, false, aaiExtMap); - } - metricLog.post(); - - } catch (AAIException e) { - // send error response - ex = e; - templateVars.add("POST Search"); - templateVars.add("getModelQueryResponse"); - response = Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) - .build(); - } catch (Exception e) { - // send error response - ex = new AAIException("AAI_4000", e); - templateVars.add("POST Search"); - templateVars.add("getModelQueryResponse"); - response = Response - .status(Status.INTERNAL_SERVER_ERROR) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); - } finally { - // log success or failure - if (ex != null) { - ErrorLogHelper.logException(ex); - } - } - return response; - } + private static final Logger LOGGER = + LoggerFactory.getLogger(ModelAndNamedQueryRestProvider.class); + + public static final String NAMED_QUERY = "/named-query"; + + public static final String MODEL_QUERY = "/model"; + + private SearchGraph searchGraph; + + private SchemaVersions schemaVersions; + + @Autowired + public ModelAndNamedQueryRestProvider(SearchGraph searchGraph, SchemaVersions schemaVersions) { + this.searchGraph = searchGraph; + this.schemaVersions = schemaVersions; + } + + /** + * Gets the named query response. + * + * @param headers the headers + * @param req the req + * @param queryParameters the query parameters + * @return the named query response + */ + /* ---------------- Start Named Query --------------------- */ + @POST + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Path(NAMED_QUERY) + public Response getNamedQueryResponse(@Context HttpHeaders headers, + @Context HttpServletRequest req, String queryParameters, @Context UriInfo info) { + return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, + new AaiCallable<Response>() { + @Override + public Response process() { + return processNamedQueryResponse(headers, req, queryParameters); + } + }); + } + + public Response processNamedQueryResponse(@Context HttpHeaders headers, + @Context HttpServletRequest req, String queryParameters) { + AAIException ex = null; + Response response; + String fromAppId; + String transId; + + ArrayList<String> templateVars = new ArrayList<>(); + try { + fromAppId = getFromAppId(headers); + transId = getTransId(headers); + + AAIExtensionMap aaiExtMap = new AAIExtensionMap(); + aaiExtMap.setHttpHeaders(headers); + aaiExtMap.setServletRequest(req); + aaiExtMap.setApiVersion(schemaVersions.getDefaultVersion().toString()); + // only consider header value for search + + AaiDBTraversalMetricLog metricLog = + new AaiDBTraversalMetricLog(AAIConstants.AAI_TRAVERSAL_MS); + String uriString = req.getRequestURI(); + Optional<URI> o; + if (uriString != null) { + o = Optional.of(new URI(uriString)); + } else { + o = Optional.empty(); + } + metricLog.pre(o); + + response = searchGraph.runNamedQuery(fromAppId, transId, queryParameters, aaiExtMap); + metricLog.post(); + + } catch (AAIException e) { + // send error response + ex = e; + templateVars.add("POST Search"); + templateVars.add("getNamedQueryResponse"); + response = Response + .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); + } catch (Exception e) { + // send error response + ex = new AAIException("AAI_4000", e); + templateVars.add("POST Search"); + templateVars.add("getNamedQueryResponse"); + response = Response + .status(Status.INTERNAL_SERVER_ERROR).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + } finally { + // log success or failure + if (ex != null) { + ErrorLogHelper.logException(ex); + } + } + return response; + } + + /** + * Gets the model query response. + * + * @param headers the headers + * @param req the req + * @param inboundPayload the inbound payload + * @param action the action + * @return the model query response + */ + /* ---------------- Start Named Query --------------------- */ + @POST + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Path(MODEL_QUERY) + public Response getModelQueryResponse(@Context HttpHeaders headers, + @Context HttpServletRequest req, String inboundPayload, @QueryParam("action") String action, + @Context UriInfo info) { + return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, + new AaiCallable<Response>() { + @Override + public Response process() { + return processModelQueryResponse(headers, req, inboundPayload, action); + } + }); + } + + public Response processModelQueryResponse(@Context HttpHeaders headers, + @Context HttpServletRequest req, String inboundPayload, + @QueryParam("action") String action) { + AAIException ex = null; + Response response; + String fromAppId; + String transId; + ArrayList<String> templateVars = new ArrayList<>(); + try { + fromAppId = getFromAppId(headers); + transId = getTransId(headers); + + AAIExtensionMap aaiExtMap = new AAIExtensionMap(); + aaiExtMap.setHttpHeaders(headers); + aaiExtMap.setServletRequest(req); + aaiExtMap.setApiVersion(schemaVersions.getDefaultVersion().toString()); + aaiExtMap.setFromAppId(fromAppId); + aaiExtMap.setTransId(transId); + + // only consider header value for search + + AaiDBTraversalMetricLog metricLog = + new AaiDBTraversalMetricLog(AAIConstants.AAI_TRAVERSAL_MS); + String uriString = req.getRequestURI(); + Optional<URI> o; + if (uriString != null) { + o = Optional.of(new URI(uriString)); + } else { + o = Optional.empty(); + } + metricLog.pre(o); + if (action != null && action.equalsIgnoreCase("DELETE")) { + response = searchGraph.executeModelOperation(fromAppId, transId, inboundPayload, + true, aaiExtMap); + } else { + response = searchGraph.executeModelOperation(fromAppId, transId, inboundPayload, + false, aaiExtMap); + } + metricLog.post(); + + } catch (AAIException e) { + // send error response + ex = e; + templateVars.add("POST Search"); + templateVars.add("getModelQueryResponse"); + response = Response + .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); + } catch (Exception e) { + // send error response + ex = new AAIException("AAI_4000", e); + templateVars.add("POST Search"); + templateVars.add("getModelQueryResponse"); + response = Response + .status(Status.INTERNAL_SERVER_ERROR).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + } finally { + // log success or failure + if (ex != null) { + ErrorLogHelper.logException(ex); + } + } + return response; + } } 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 366e7df..fc3847e 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,11 +19,15 @@ */ package org.onap.aai.rest.search; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit; +import java.io.FileNotFoundException; +import java.util.*; +import java.util.regex.Pattern; + +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; + import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.javatuples.Pair; @@ -31,87 +35,84 @@ import org.onap.aai.exceptions.AAIException; import org.onap.aai.restcore.search.GroovyQueryBuilder; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.serialization.queryformats.SubGraphStyle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.io.FileNotFoundException; -import java.util.*; -import java.util.regex.Pattern; +public class NodeQueryProcessor extends GroovyShellImpl { -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.core.MultivaluedMap; + private static Logger logger = LoggerFactory.getLogger(NodeQueryProcessor.class); -public class NodeQueryProcessor extends GroovyShellImpl { + protected String nodeType; + private MultivaluedMap<String, String> nodeQueryParams = new MultivaluedHashMap<>(); + protected final Optional<Collection<Vertex>> vertices; + protected static Pattern p = Pattern.compile("query/(.*+)"); + protected Optional<String> gremlin; + protected final TransactionalGraphEngine dbEngine; + protected GroovyQueryBuilder queryBuilder = new GroovyQueryBuilder(); + + protected NodeQueryProcessor(Builder builder) { + super(builder); + this.nodeQueryParams = builder.uriParams; + if (builder.getNodeType().isPresent()) { + this.nodeType = builder.getNodeType().get(); + } + this.dbEngine = builder.getDbEngine(); + this.vertices = builder.getVertices(); + + } + + public Pair<String, Map<String, Object>> createQuery() throws AAIException { + Map<String, Object> params = new HashMap<>(); + + Long timeNowInMilliSecs = System.currentTimeMillis(); + Long startTime = 0L; + if (nodeQueryParams.containsKey("hours")) { + Long hoursInMilliSec = + TimeUnit.HOURS.toMillis(Long.parseLong(nodeQueryParams.getFirst("hours"))); + startTime = timeNowInMilliSecs - hoursInMilliSec; + } else if (nodeQueryParams.containsKey("date-time")) { + Long dateTime = Long.parseLong(nodeQueryParams.getFirst("date-time")); + startTime = dateTime; + } + + String query = "builder.getVerticesByProperty('aai-node-type', nodeType)" + + ".or(builder.newInstance().getVerticesGreaterThanProperty('aai-created-ts',startTime)," + + " builder.newInstance().getVerticesGreaterThanProperty('aai-last-mod-ts',startTime)" + + ")"; + + params.put("startTime", startTime); + params.put("nodeType", nodeType); + + query = queryBuilder.executeTraversal(dbEngine, query, params); + + String startPrefix = "g.V()"; + + query = startPrefix + query; + + if (logger.isDebugEnabled()) { + logger.debug("Converted to gremlin query without the start vertices \n {}", query); + } + + return new Pair<>(query, params); + } + + public List<Object> execute(SubGraphStyle style) throws FileNotFoundException, AAIException { + final List<Object> resultVertices = new Vector<>(); + + Pair<String, Map<String, Object>> tuple = this.createQuery(); + String query = tuple.getValue0(); + Map<String, Object> params = tuple.getValue1(); + + if (query.equals("")) { + // nothing to do, just exit + return new ArrayList<>(); + } + GraphTraversal<?, ?> g = + this.runQuery(query, params, dbEngine.asAdmin().getTraversalSource()); + + resultVertices.addAll(g.toList()); - private static Logger logger = LoggerFactory.getLogger(NodeQueryProcessor.class); - - protected String nodeType; - private MultivaluedMap<String, String> nodeQueryParams = new MultivaluedHashMap<>(); - protected final Optional<Collection<Vertex>> vertices; - protected static Pattern p = Pattern.compile("query/(.*+)"); - protected Optional<String> gremlin; - protected final TransactionalGraphEngine dbEngine; - protected GroovyQueryBuilder queryBuilder = new GroovyQueryBuilder(); - - protected NodeQueryProcessor(Builder builder) { - super(builder); - this.nodeQueryParams = builder.uriParams; - if(builder.getNodeType().isPresent()) { - this.nodeType = builder.getNodeType().get(); - } - this.dbEngine = builder.getDbEngine(); - this.vertices = builder.getVertices(); - - } - - public Pair<String, Map<String, Object>> createQuery() throws AAIException { - Map<String, Object> params = new HashMap<>(); - - Long timeNowInMilliSecs = System.currentTimeMillis(); - Long startTime = 0L; - if(nodeQueryParams.containsKey("hours")){ - Long hoursInMilliSec = TimeUnit.HOURS.toMillis(Long.parseLong(nodeQueryParams.getFirst("hours"))); - startTime = timeNowInMilliSecs - hoursInMilliSec; - } - else if(nodeQueryParams.containsKey("date-time")){ - Long dateTime = Long.parseLong(nodeQueryParams.getFirst("date-time")); - startTime = dateTime; - } - - String query = "builder.getVerticesByProperty('aai-node-type', nodeType)" - + ".or(builder.newInstance().getVerticesGreaterThanProperty('aai-created-ts',startTime)," - + " builder.newInstance().getVerticesGreaterThanProperty('aai-last-mod-ts',startTime)" + ")"; - - params.put("startTime", startTime); - params.put("nodeType", nodeType); - - query = queryBuilder.executeTraversal(dbEngine, query, params); - - String startPrefix = "g.V()"; - - query = startPrefix + query; - - if (logger.isDebugEnabled()) { - logger.debug("Converted to gremlin query without the start vertices \n {}", query); - } - - return new Pair<>(query, params); - } - - public List<Object> execute(SubGraphStyle style) throws FileNotFoundException, AAIException { - final List<Object> resultVertices = new Vector<>(); - - Pair<String, Map<String, Object>> tuple = this.createQuery(); - String query = tuple.getValue0(); - Map<String, Object> params = tuple.getValue1(); - - if (query.equals("")) { - // nothing to do, just exit - return new ArrayList<>(); - } - GraphTraversal<?, ?> g = this.runQuery(query, params, dbEngine.asAdmin().getTraversalSource()); - - resultVertices.addAll(g.toList()); - - return resultVertices; - } + return resultVertices; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/QueryProcessorType.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/QueryProcessorType.java index c8e1d14..8e4c7cf 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/search/QueryProcessorType.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/QueryProcessorType.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -21,6 +21,5 @@ package org.onap.aai.rest.search; public enum QueryProcessorType { - GREMLIN_SERVER, - LOCAL_GROOVY + GREMLIN_SERVER, LOCAL_GROOVY } 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 index ea1b62f..49986de 100644 --- 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,19 +19,21 @@ */ package org.onap.aai.rest.search; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.att.eelf.configuration.EELFManager; + +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.PostConstruct; + import org.onap.aai.restclient.RestClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Qualifier; +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 Logger logger = LoggerFactory.getLogger(SchemaServiceCQConfig.class); @@ -46,19 +48,20 @@ public class SchemaServiceCQConfig extends CQConfig { @PostConstruct public void initialize() { - //Call SchemaService to get custom queries + // Call SchemaService to get custom queries retrieveCustomQueries(); } public void retrieveCustomQueries() { - /* - Call Schema MS to get custom queries using RestTemplate - */ + /* + * Call Schema MS to get custom queries using RestTemplate + */ logger.info("Calling the SchemaService to retrieve stored queries"); String content = ""; Map<String, String> headersMap = new HashMap<>(); - ResponseEntity<String> schemaResponse = restClient.getGetRequest(content, customQueriesUri, headersMap); + ResponseEntity<String> schemaResponse = + restClient.getGetRequest(content, customQueriesUri, headersMap); queryConfig = new GetCustomQueryConfig(schemaResponse.getBody()); } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/SearchProvider.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/SearchProvider.java index 1db2699..17edbc5 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/search/SearchProvider.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/SearchProvider.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,6 +20,17 @@ package org.onap.aai.rest.search; import io.micrometer.core.annotation.Timed; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; + import org.onap.aai.aailog.logs.AaiDBTraversalMetricLog; import org.onap.aai.concurrent.AaiCallable; import org.onap.aai.dbgraphmap.SearchGraph; @@ -46,15 +57,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - /** * Implements the search subdomain in the REST API. All API calls must include X-FromAppId and * X-TransactionId in the header. @@ -78,8 +80,8 @@ public class SearchProvider extends RESTAPI { private String basePath; @Autowired - public SearchProvider(LoaderFactory loaderFactory, SearchGraph searchGraph, SchemaVersions schemaVersions, - @Value("${schema.uri.base.path}") String basePath) { + public SearchProvider(LoaderFactory loaderFactory, SearchGraph searchGraph, + SchemaVersions schemaVersions, @Value("${schema.uri.base.path}") String basePath) { this.loaderFactory = loaderFactory; this.searchGraph = searchGraph; this.schemaVersions = schemaVersions; @@ -101,27 +103,29 @@ public class SearchProvider extends RESTAPI { @GET @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @Path(GENERIC_QUERY) - public Response getGenericQueryResponse(@Context HttpHeaders headers, @Context HttpServletRequest req, - @QueryParam("start-node-type") final String startNodeType, - @QueryParam("key") final List<String> startNodeKeyParams, - @QueryParam("include") final List<String> includeNodeTypes, @QueryParam("depth") final int depth, - @PathParam("version") String versionParam, @Context UriInfo info) { - return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, - TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, - new AaiCallable<Response>() { - @Override - public Response process() { - return processGenericQueryResponse(headers, req, startNodeType, startNodeKeyParams, - includeNodeTypes, depth, versionParam); - } - }); + public Response getGenericQueryResponse(@Context HttpHeaders headers, + @Context HttpServletRequest req, @QueryParam("start-node-type") final String startNodeType, + @QueryParam("key") final List<String> startNodeKeyParams, + @QueryParam("include") final List<String> includeNodeTypes, + @QueryParam("depth") final int depth, @PathParam("version") String versionParam, + @Context UriInfo info) { + return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, + new AaiCallable<Response>() { + @Override + public Response process() { + return processGenericQueryResponse(headers, req, startNodeType, + startNodeKeyParams, includeNodeTypes, depth, versionParam); + } + }); } - public Response processGenericQueryResponse(@Context HttpHeaders headers, @Context HttpServletRequest req, - @QueryParam("start-node-type") final String startNodeType, - @QueryParam("key") final List<String> startNodeKeyParams, - @QueryParam("include") final List<String> includeNodeTypes, @QueryParam("depth") final int depth, - @PathParam("version") String versionParam) { + public Response processGenericQueryResponse(@Context HttpHeaders headers, + @Context HttpServletRequest req, @QueryParam("start-node-type") final String startNodeType, + @QueryParam("key") final List<String> startNodeKeyParams, + @QueryParam("include") final List<String> includeNodeTypes, + @QueryParam("depth") final int depth, @PathParam("version") String versionParam) { AAIException ex = null; Response searchResult; @@ -137,17 +141,20 @@ public class SearchProvider extends RESTAPI { final ModelType factoryType = ModelType.MOXY; Loader loader = loaderFactory.createLoaderForVersion(factoryType, version); - TransactionalGraphEngine dbEngine = new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader); + TransactionalGraphEngine dbEngine = + new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader); DBSerializer dbSerializer = new DBSerializer(version, dbEngine, factoryType, fromAppId); - UrlBuilder urlBuilder = new UrlBuilder(version, dbSerializer, schemaVersions, this.basePath); + UrlBuilder urlBuilder = + new UrlBuilder(version, dbSerializer, schemaVersions, this.basePath); - AaiDBTraversalMetricLog metricLog = new AaiDBTraversalMetricLog (AAIConstants.AAI_TRAVERSAL_MS); + AaiDBTraversalMetricLog metricLog = + new AaiDBTraversalMetricLog(AAIConstants.AAI_TRAVERSAL_MS); metricLog.pre(Optional.of(new URI(req.getRequestURI()))); - searchResult = searchGraph - .runGenericQuery(new GenericQueryBuilder().setHeaders(headers).setStartNodeType(startNodeType) - .setStartNodeKeyParams(startNodeKeyParams).setIncludeNodeTypes(includeNodeTypes) - .setDepth(depth).setDbEngine(dbEngine).setLoader(loader).setUrlBuilder(urlBuilder)); + searchResult = searchGraph.runGenericQuery(new GenericQueryBuilder().setHeaders(headers) + .setStartNodeType(startNodeType).setStartNodeKeyParams(startNodeKeyParams) + .setIncludeNodeTypes(includeNodeTypes).setDepth(depth).setDbEngine(dbEngine) + .setLoader(loader).setUrlBuilder(urlBuilder)); metricLog.post(); @@ -156,17 +163,19 @@ public class SearchProvider extends RESTAPI { ex = e; templateVars.add("GET Search"); templateVars.add("getGenericQueryResponse"); - searchResult = Response.status(e.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) - .build(); + searchResult = Response + .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); } catch (Exception e) { // send error response ex = new AAIException("AAI_4000", e); templateVars.add("GET Search"); templateVars.add("getGenericQueryResponse"); - searchResult = Response.status(Status.INTERNAL_SERVER_ERROR) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); + searchResult = Response + .status(Status.INTERNAL_SERVER_ERROR).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); } finally { // log success or failure if (ex != null) { @@ -193,28 +202,32 @@ public class SearchProvider extends RESTAPI { @GET @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @Path(NODES_QUERY) - public Response getNodesQueryResponse(@Context HttpHeaders headers, @Context HttpServletRequest req, - @QueryParam("search-node-type") final String searchNodeType, - @QueryParam("edge-filter") final List<String> edgeFilterList, - @QueryParam("filter") final List<String> filterList, @PathParam("version") String versionParam, - @Context UriInfo info) + public Response getNodesQueryResponse(@Context HttpHeaders headers, + @Context HttpServletRequest req, + @QueryParam("search-node-type") final String searchNodeType, + @QueryParam("edge-filter") final List<String> edgeFilterList, + @QueryParam("filter") final List<String> filterList, + @PathParam("version") String versionParam, @Context UriInfo info) { - return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, - TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, - new AaiCallable<Response>() { - @Override - public Response process() { - return processNodesQueryResponse(headers, req, searchNodeType, edgeFilterList, filterList, - versionParam); - } - }); + return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_APP, + TraversalConstants.AAI_TRAVERSAL_TIMEOUT_LIMIT, headers, info, HttpMethod.GET, + new AaiCallable<Response>() { + @Override + public Response process() { + return processNodesQueryResponse(headers, req, searchNodeType, edgeFilterList, + filterList, versionParam); + } + }); } - public Response processNodesQueryResponse(@Context HttpHeaders headers, @Context HttpServletRequest req, - @QueryParam("search-node-type") final String searchNodeType, - @QueryParam("edge-filter") final List<String> edgeFilterList, - @QueryParam("filter") final List<String> filterList, @PathParam("version") String versionParam) { + public Response processNodesQueryResponse(@Context HttpHeaders headers, + @Context HttpServletRequest req, + @QueryParam("search-node-type") final String searchNodeType, + @QueryParam("edge-filter") final List<String> edgeFilterList, + @QueryParam("filter") final List<String> filterList, + @PathParam("version") String versionParam) { AAIException ex = null; Response searchResult; @@ -231,15 +244,18 @@ public class SearchProvider extends RESTAPI { final ModelType factoryType = ModelType.MOXY; Loader loader = loaderFactory.createLoaderForVersion(factoryType, version); - TransactionalGraphEngine dbEngine = new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader); + TransactionalGraphEngine dbEngine = + new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader); DBSerializer dbSerializer = new DBSerializer(version, dbEngine, factoryType, fromAppId); - UrlBuilder urlBuilder = new UrlBuilder(version, dbSerializer, schemaVersions, this.basePath); - + UrlBuilder urlBuilder = + new UrlBuilder(version, dbSerializer, schemaVersions, this.basePath); - AaiDBTraversalMetricLog metricLog = new AaiDBTraversalMetricLog (AAIConstants.AAI_TRAVERSAL_MS); + AaiDBTraversalMetricLog metricLog = + new AaiDBTraversalMetricLog(AAIConstants.AAI_TRAVERSAL_MS); metricLog.pre(Optional.of(new URI(req.getRequestURI()))); - searchResult = searchGraph.runNodesQuery(new NodesQueryBuilder().setHeaders(headers) - .setTargetNodeType(searchNodeType).setEdgeFilterParams(edgeFilterList).setFilterParams(filterList) + searchResult = searchGraph.runNodesQuery( + new NodesQueryBuilder().setHeaders(headers).setTargetNodeType(searchNodeType) + .setEdgeFilterParams(edgeFilterList).setFilterParams(filterList) .setDbEngine(dbEngine).setLoader(loader).setUrlBuilder(urlBuilder)); metricLog.post(); @@ -249,17 +265,19 @@ public class SearchProvider extends RESTAPI { ex = e; templateVars.add("GET Search"); templateVars.add("getNodesQueryResponse"); - searchResult = Response.status(e.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) - .build(); + searchResult = Response + .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); } catch (Exception e) { // send error response ex = new AAIException("AAI_4000", e); templateVars.add("GET Search"); templateVars.add("getNodesQueryResponse"); - searchResult = Response.status(Status.INTERNAL_SERVER_ERROR) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) - .build(); + searchResult = Response + .status(Status.INTERNAL_SERVER_ERROR).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); } finally { // log success or failure if (ex != null) { @@ -269,6 +287,4 @@ public class SearchProvider extends RESTAPI { return searchResult; } - - } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java b/aai-traversal/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java index c92d818..e24013b 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/security/WebSecurityConfig.java @@ -11,7 +11,7 @@ * 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 + * 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, @@ -23,6 +23,7 @@ * ============LICENSE_END========================================================= */ package org.onap.aai.rest.security; + import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; import org.keycloak.adapters.springsecurity.KeycloakConfiguration; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; @@ -40,35 +41,36 @@ import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; import org.springframework.security.web.session.HttpSessionEventPublisher; + @Profile("keycloak") @KeycloakConfiguration @Import({KeycloakSpringBootConfigResolver.class}) public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { - KeycloakAuthenticationProvider keycloakAuthenticationProvider - = keycloakAuthenticationProvider(); - keycloakAuthenticationProvider.setGrantedAuthoritiesMapper( - new SimpleAuthorityMapper()); + KeycloakAuthenticationProvider keycloakAuthenticationProvider = + keycloakAuthenticationProvider(); + keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(keycloakAuthenticationProvider); } + @Bean public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() { return new ServletListenerRegistrationBean<>(new HttpSessionEventPublisher()); } + @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { - return new RegisterSessionAuthenticationStrategy( - new SessionRegistryImpl()); + return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } + @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); - http.authorizeRequests() - .antMatchers("/**") - .permitAll().and().csrf().disable(); + http.authorizeRequests().antMatchers("/**").permitAll().and().csrf().disable(); } + @Override public void configure(WebSecurity web) throws Exception { web.ignoring().regexMatchers("^.*/util/echo$"); diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/util/AAIExtensionMap.java b/aai-traversal/src/main/java/org/onap/aai/rest/util/AAIExtensionMap.java index 0aa70e3..4e5651d 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/util/AAIExtensionMap.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/util/AAIExtensionMap.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,6 +20,14 @@ package org.onap.aai.rest.util; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.UriInfo; + import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; @@ -29,13 +37,6 @@ import org.onap.aai.rest.db.DBRequest; import org.onap.aai.rest.db.HttpEntry; import org.onap.aai.serialization.engines.TransactionalGraphEngine; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.UriInfo; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; - public class AAIExtensionMap { // ======================================================================= // Attribute | Type diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/util/ConvertQueryPropertiesToJson.java b/aai-traversal/src/main/java/org/onap/aai/rest/util/ConvertQueryPropertiesToJson.java index f16e700..f3ec5f8 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/util/ConvertQueryPropertiesToJson.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/util/ConvertQueryPropertiesToJson.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -26,86 +26,88 @@ import java.util.List; import java.util.Properties; public class ConvertQueryPropertiesToJson { - - private static final int MAX_FILE_SIZE = 256000; - - private void addStart( StringBuilder sb ) { - sb.append("{\n \"stored-queries\":[{\n"); - } - - private void addRequiredQueryProperties( StringBuilder sb, List<String> rqd ) { - Iterator it = rqd.iterator(); - sb.append(" \"query\":{\n \"required-properties\":["); - while( it.hasNext()) { - sb.append("\"" + it.next() + "\""); - if ( it.hasNext()) { - sb.append(","); - } - } - sb.append("]\n },\n"); - } - - private void addAnotherQuery( StringBuilder sb, String queryName, String query, List<String> rqd ) { - sb.append(" \"" + queryName + "\":{\n"); - if ( !rqd.isEmpty()) { - addRequiredQueryProperties( sb, rqd); - } - sb.append(" \"stored-query\":\"" + query + "\"\n }\n },{\n"); - } - - private void addLastQuery( StringBuilder sb, String queryName, String query, List<String> rqd ) { - sb.append(" \"" + queryName + "\":{\n"); - if ( !rqd.isEmpty() ) { - addRequiredQueryProperties( sb, rqd); - } - sb.append(" \"stored-query\":\"" + query + "\"\n }\n }]\n}\n"); - } - - private String get2ndParameter( String paramString) { - String endParams = paramString.substring(0, paramString.indexOf(')')); - String result = endParams.substring(endParams.indexOf(',') + 1 ); - String lastParam = result.trim(); - if ( lastParam.startsWith("\\") || lastParam.startsWith("'") || lastParam.startsWith("new ") ){ - return null; - } - - return lastParam; - } - - private List<String> findRqdProperties( String query) { - String[] parts = query.split("getVerticesByProperty"); - List<String> result = new ArrayList<>(); - if ( parts.length == 1 ) - return result; - int count = 0; - String foundRqdProperty; - while ( count++ < parts.length - 1 ) { - foundRqdProperty = get2ndParameter(parts[count]); - if ( foundRqdProperty != null && !result.contains(foundRqdProperty)) { - result.add(foundRqdProperty); - } - } - return result; - } - public String convertProperties( Properties props ) { - Enumeration<?> e = props.propertyNames(); - StringBuilder sb = new StringBuilder(MAX_FILE_SIZE); - String queryName; - String query; - addStart( sb ); - List<String> rqd; - while ( e.hasMoreElements()) { - queryName = (String)e.nextElement(); - query = props.getProperty(queryName).trim().replace("\"", "\\\""); - rqd = findRqdProperties( query); - if ( e.hasMoreElements()) { - addAnotherQuery( sb, queryName, query, rqd); - } else { - addLastQuery( sb, queryName, query, rqd); - } - } - + private static final int MAX_FILE_SIZE = 256000; + + private void addStart(StringBuilder sb) { + sb.append("{\n \"stored-queries\":[{\n"); + } + + private void addRequiredQueryProperties(StringBuilder sb, List<String> rqd) { + Iterator it = rqd.iterator(); + sb.append(" \"query\":{\n \"required-properties\":["); + while (it.hasNext()) { + sb.append("\"" + it.next() + "\""); + if (it.hasNext()) { + sb.append(","); + } + } + sb.append("]\n },\n"); + } + + private void addAnotherQuery(StringBuilder sb, String queryName, String query, + List<String> rqd) { + sb.append(" \"" + queryName + "\":{\n"); + if (!rqd.isEmpty()) { + addRequiredQueryProperties(sb, rqd); + } + sb.append(" \"stored-query\":\"" + query + "\"\n }\n },{\n"); + } + + private void addLastQuery(StringBuilder sb, String queryName, String query, List<String> rqd) { + sb.append(" \"" + queryName + "\":{\n"); + if (!rqd.isEmpty()) { + addRequiredQueryProperties(sb, rqd); + } + sb.append(" \"stored-query\":\"" + query + "\"\n }\n }]\n}\n"); + } + + private String get2ndParameter(String paramString) { + String endParams = paramString.substring(0, paramString.indexOf(')')); + String result = endParams.substring(endParams.indexOf(',') + 1); + String lastParam = result.trim(); + if (lastParam.startsWith("\\") || lastParam.startsWith("'") + || lastParam.startsWith("new ")) { + return null; + } + + return lastParam; + } + + private List<String> findRqdProperties(String query) { + String[] parts = query.split("getVerticesByProperty"); + List<String> result = new ArrayList<>(); + if (parts.length == 1) + return result; + int count = 0; + String foundRqdProperty; + while (count++ < parts.length - 1) { + foundRqdProperty = get2ndParameter(parts[count]); + if (foundRqdProperty != null && !result.contains(foundRqdProperty)) { + result.add(foundRqdProperty); + } + } + return result; + } + + public String convertProperties(Properties props) { + Enumeration<?> e = props.propertyNames(); + StringBuilder sb = new StringBuilder(MAX_FILE_SIZE); + String queryName; + String query; + addStart(sb); + List<String> rqd; + while (e.hasMoreElements()) { + queryName = (String) e.nextElement(); + query = props.getProperty(queryName).trim().replace("\"", "\\\""); + rqd = findRqdProperties(query); + if (e.hasMoreElements()) { + addAnotherQuery(sb, queryName, query, rqd); + } else { + addLastQuery(sb, queryName, query, rqd); + } + } + return sb.toString(); - } + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/util/EchoResponse.java b/aai-traversal/src/main/java/org/onap/aai/rest/util/EchoResponse.java index 16c2618..d0ba708 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/util/EchoResponse.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/util/EchoResponse.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -42,79 +42,79 @@ import org.onap.aai.restcore.RESTAPI; */ @Path("/util") public class EchoResponse extends RESTAPI { - - protected static String authPolicyFunctionName = "util"; - - public static final String ECHO_PATH = "/echo"; - - /** - * Simple health-check API that echos back the X-FromAppId and X-TransactionId to clients. - * If there is a query string, a transaction gets logged into hbase, proving the application is connected to the data store. - * If there is no query string, no transacction logging is done to hbase. - * - * @param headers the headers - * @param req the req - * @param myAction if exists will cause transaction to be logged to hbase - * @return the response - */ - @GET - @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) - @Path(ECHO_PATH) - public Response echoResult(@Context HttpHeaders headers, @Context HttpServletRequest req, - @QueryParam("action") String myAction) { - AAIException ex = null; - Response response; - String fromAppId; - String transId; - - try { - fromAppId = getFromAppId(headers ); - transId = getTransId(headers); - } catch (AAIException e) { - ArrayList<String> templateVars = new ArrayList<>(); - templateVars.add("PUT uebProvider"); - templateVars.add("addTopic"); - return Response - .status(e.getErrorObject().getHTTPResponseCode()) - .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) - .build(); - } - - try { - - HashMap<AAIException, ArrayList<String>> exceptionList = new HashMap<>(); - - ArrayList<String> templateVars = new ArrayList<>(); - templateVars.add(fromAppId); - templateVars.add(transId); - - exceptionList.put(new AAIException("AAI_0002", "OK"), templateVars); - - response = Response.status(Status.OK) - .entity(ErrorLogHelper.getRESTAPIInfoResponse( - headers.getAcceptableMediaTypes(), exceptionList)) - .build(); - - } catch (Exception e) { - ex = new AAIException("AAI_4000", e); - ArrayList<String> templateVars = new ArrayList<>(); - templateVars.add(Action.GET.name()); - templateVars.add(fromAppId +" "+transId); - - response = Response - .status(Status.INTERNAL_SERVER_ERROR) - .entity(ErrorLogHelper.getRESTAPIErrorResponse( - headers.getAcceptableMediaTypes(), ex, - templateVars)).build(); - - } finally { - if (ex != null) { - ErrorLogHelper.logException(ex); - } - - } - - return response; - } + + protected static String authPolicyFunctionName = "util"; + + public static final String ECHO_PATH = "/echo"; + + /** + * Simple health-check API that echos back the X-FromAppId and X-TransactionId to clients. + * If there is a query string, a transaction gets logged into hbase, proving the application is + * connected to the data store. + * If there is no query string, no transacction logging is done to hbase. + * + * @param headers the headers + * @param req the req + * @param myAction if exists will cause transaction to be logged to hbase + * @return the response + */ + @GET + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + @Path(ECHO_PATH) + public Response echoResult(@Context HttpHeaders headers, @Context HttpServletRequest req, + @QueryParam("action") String myAction) { + AAIException ex = null; + Response response; + String fromAppId; + String transId; + + try { + fromAppId = getFromAppId(headers); + transId = getTransId(headers); + } catch (AAIException e) { + ArrayList<String> templateVars = new ArrayList<>(); + templateVars.add("PUT uebProvider"); + templateVars.add("addTopic"); + return Response + .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); + } + + try { + + HashMap<AAIException, ArrayList<String>> exceptionList = new HashMap<>(); + + ArrayList<String> templateVars = new ArrayList<>(); + templateVars.add(fromAppId); + templateVars.add(transId); + + exceptionList.put(new AAIException("AAI_0002", "OK"), templateVars); + + response = Response + .status(Status.OK).entity(ErrorLogHelper + .getRESTAPIInfoResponse(headers.getAcceptableMediaTypes(), exceptionList)) + .build(); + + } catch (Exception e) { + ex = new AAIException("AAI_4000", e); + ArrayList<String> templateVars = new ArrayList<>(); + templateVars.add(Action.GET.name()); + templateVars.add(fromAppId + " " + transId); + + response = Response + .status(Status.INTERNAL_SERVER_ERROR).entity(ErrorLogHelper + .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + + } finally { + if (ex != null) { + ErrorLogHelper.logException(ex); + } + + } + + return response; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/util/LogFormatTools.java b/aai-traversal/src/main/java/org/onap/aai/rest/util/LogFormatTools.java index 931ab0b..f7539a0 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/util/LogFormatTools.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/util/LogFormatTools.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -25,11 +25,11 @@ import java.time.format.DateTimeFormatter; public class LogFormatTools { - private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; - private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern(DATE_FORMAT) - .withZone(ZoneOffset.UTC); - - public static String getCurrentDateTime() { - return DTF.format(ZonedDateTime.now()); - } + private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + private static final DateTimeFormatter DTF = + DateTimeFormatter.ofPattern(DATE_FORMAT).withZone(ZoneOffset.UTC); + + public static String getCurrentDateTime() { + return DTF.format(ZonedDateTime.now()); + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/util/ValidateEncoding.java b/aai-traversal/src/main/java/org/onap/aai/rest/util/ValidateEncoding.java index 7d04bf7..fcf7e42 100644 --- a/aai-traversal/src/main/java/org/onap/aai/rest/util/ValidateEncoding.java +++ b/aai-traversal/src/main/java/org/onap/aai/rest/util/ValidateEncoding.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -32,131 +32,133 @@ import org.springframework.web.util.UriUtils; */ public class ValidateEncoding { - private final String encoding = "UTF-8"; - - /** - * Instantiates a new validate encoding. - */ - private ValidateEncoding() { - - } - - /** - * The Class Helper. - */ - private static class Helper { - - /** The Constant INSTANCE. */ - private static final ValidateEncoding INSTANCE = new ValidateEncoding(); - } - - /** - * Gets the single instance of ValidateEncoding. - * - * @return single instance of ValidateEncoding - */ - public static ValidateEncoding getInstance() { - return Helper.INSTANCE; - } - - /** - * Validate. - * - * @param uri the uri - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - public boolean validate(URI uri) throws UnsupportedEncodingException { - boolean result = true; - if (!validatePath(uri.getRawPath())) { - result = false; - } - /*if (!validateQueryParams(uri.getRawQuery())) { - result = false; - } //TODO - */ - - return result; - } - - /** - * Validate. - * - * @param info the info - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - public boolean validate(UriInfo info) throws UnsupportedEncodingException { - boolean result = true; - if (!validatePath(info.getPath(false))) { - result = false; - } - if (!validateQueryParams(info.getQueryParameters(false))) { - result = false; - } - - return result; - } - - /** - * Validate path. - * - * @param path the path - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - private boolean validatePath(String path) throws UnsupportedEncodingException { - String[] segments = path.split("/"); - boolean valid = true; - for (String segment : segments) { - if (!this.checkEncoding(segment)) { - valid = false; - } - } - - return valid; - - } - - /** - * Validate query params. - * - * @param params the params - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - private boolean validateQueryParams(MultivaluedMap<String, String> params) throws UnsupportedEncodingException { - boolean valid = true; - - for (String key : params.keySet()) { - if (!this.checkEncoding(key)) { - valid = false; - } - for (String item : params.get(key)) { - if(item.contains("+")){ - item = item.replaceAll("\\+", "%20"); - } - if (!this.checkEncoding(item)) { - valid = false; - } - } - } - return valid; - } - - /** - * Check encoding. - * - * @param segment the segment - * @return true, if successful - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - private boolean checkEncoding(String segment) throws UnsupportedEncodingException { - boolean result = false; - String decode = UriUtils.decode(segment, encoding); - String encode = UriUtils.encode(decode, encoding); - result = segment.equals(encode); - - return result; - } + private final String encoding = "UTF-8"; + + /** + * Instantiates a new validate encoding. + */ + private ValidateEncoding() { + + } + + /** + * The Class Helper. + */ + private static class Helper { + + /** The Constant INSTANCE. */ + private static final ValidateEncoding INSTANCE = new ValidateEncoding(); + } + + /** + * Gets the single instance of ValidateEncoding. + * + * @return single instance of ValidateEncoding + */ + public static ValidateEncoding getInstance() { + return Helper.INSTANCE; + } + + /** + * Validate. + * + * @param uri the uri + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + public boolean validate(URI uri) throws UnsupportedEncodingException { + boolean result = true; + if (!validatePath(uri.getRawPath())) { + result = false; + } + /* + * if (!validateQueryParams(uri.getRawQuery())) { + * result = false; + * } //TODO + */ + + return result; + } + + /** + * Validate. + * + * @param info the info + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + public boolean validate(UriInfo info) throws UnsupportedEncodingException { + boolean result = true; + if (!validatePath(info.getPath(false))) { + result = false; + } + if (!validateQueryParams(info.getQueryParameters(false))) { + result = false; + } + + return result; + } + + /** + * Validate path. + * + * @param path the path + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + private boolean validatePath(String path) throws UnsupportedEncodingException { + String[] segments = path.split("/"); + boolean valid = true; + for (String segment : segments) { + if (!this.checkEncoding(segment)) { + valid = false; + } + } + + return valid; + + } + + /** + * Validate query params. + * + * @param params the params + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + private boolean validateQueryParams(MultivaluedMap<String, String> params) + throws UnsupportedEncodingException { + boolean valid = true; + + for (String key : params.keySet()) { + if (!this.checkEncoding(key)) { + valid = false; + } + for (String item : params.get(key)) { + if (item.contains("+")) { + item = item.replaceAll("\\+", "%20"); + } + if (!this.checkEncoding(item)) { + valid = false; + } + } + } + return valid; + } + + /** + * Check encoding. + * + * @param segment the segment + * @return true, if successful + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + private boolean checkEncoding(String segment) throws UnsupportedEncodingException { + boolean result = false; + String decode = UriUtils.decode(segment, encoding); + String encode = UriUtils.encode(decode, encoding); + result = segment.equals(encode); + + return result; + } } diff --git a/aai-traversal/src/main/java/org/onap/aai/service/AuthorizationService.java b/aai-traversal/src/main/java/org/onap/aai/service/AuthorizationService.java index b4fa996..b448bc8 100644 --- a/aai-traversal/src/main/java/org/onap/aai/service/AuthorizationService.java +++ b/aai-traversal/src/main/java/org/onap/aai/service/AuthorizationService.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,15 +19,6 @@ */ package org.onap.aai.service; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.eclipse.jetty.util.security.Password; -import org.onap.aai.Profiles; -import org.onap.aai.util.AAIConstants; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Service; - -import javax.annotation.PostConstruct; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -37,6 +28,16 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; +import javax.annotation.PostConstruct; + +import org.eclipse.jetty.util.security.Password; +import org.onap.aai.Profiles; +import org.onap.aai.util.AAIConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + @Service @Profile(Profiles.ONE_WAY_SSL) public class AuthorizationService { @@ -48,45 +49,47 @@ public class AuthorizationService { private static final Base64.Encoder ENCODER = Base64.getEncoder(); @PostConstruct - public void init(){ + public void init() { String basicAuthFile = getBasicAuthFilePath(); - try(Stream<String> stream = Files.lines(Paths.get(basicAuthFile))){ + try (Stream<String> stream = Files.lines(Paths.get(basicAuthFile))) { stream.filter(line -> !line.startsWith("#")).forEach(str -> { - byte [] bytes = null; + byte[] bytes = null; String usernamePassword = null; String accessType = null; - String [] userAccessType = str.split(","); + String[] userAccessType = str.split(","); - if(userAccessType.length != 2){ - throw new RuntimeException("Please check the realm.properties file as it is not conforming to the basic auth"); + if (userAccessType.length != 2) { + throw new RuntimeException( + "Please check the realm.properties file as it is not conforming to the basic auth"); } usernamePassword = userAccessType[0]; - accessType = userAccessType[1]; + accessType = userAccessType[1]; String[] usernamePasswordArray = usernamePassword.split(":"); - if(usernamePasswordArray.length != 3){ - throw new RuntimeException("This username / pwd is not a valid entry in realm.properties"); + if (usernamePasswordArray.length != 3) { + throw new RuntimeException( + "This username / pwd is not a valid entry in realm.properties"); } String username = usernamePasswordArray[0]; String password = null; - if(str.contains("OBF:")){ + if (str.contains("OBF:")) { password = usernamePasswordArray[1] + ":" + usernamePasswordArray[2]; password = Password.deobfuscate(password); } - bytes = ENCODER.encode((username + ":" + password).getBytes(StandardCharsets.UTF_8)); + bytes = + ENCODER.encode((username + ":" + password).getBytes(StandardCharsets.UTF_8)); authorizedUsers.put(new String(bytes), accessType); - authorizedUsers.put(new String(ENCODER.encode(bytes)), accessType); }); } catch (IOException e) { @@ -94,11 +97,12 @@ public class AuthorizationService { } } - public boolean checkIfUserAuthorized(String authorization){ - return authorizedUsers.containsKey(authorization) && "admin".equals(authorizedUsers.get(authorization)); + public boolean checkIfUserAuthorized(String authorization) { + return authorizedUsers.containsKey(authorization) + && "admin".equals(authorizedUsers.get(authorization)); } - public String getBasicAuthFilePath(){ + public String getBasicAuthFilePath() { return AAIConstants.AAI_HOME_ETC_AUTH + AAIConstants.AAI_FILESEP + "realm.properties"; } } diff --git a/aai-traversal/src/main/java/org/onap/aai/service/RetiredService.java b/aai-traversal/src/main/java/org/onap/aai/service/RetiredService.java index 5989e31..b40c328 100644 --- a/aai-traversal/src/main/java/org/onap/aai/service/RetiredService.java +++ b/aai-traversal/src/main/java/org/onap/aai/service/RetiredService.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,16 +19,17 @@ */ package org.onap.aai.service; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.PropertySource; -import org.springframework.stereotype.Service; - -import javax.annotation.PostConstruct; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; import java.util.stream.Collectors; +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Service; + @Service @PropertySource("classpath:retired.properties") @PropertySource(value = "file:${server.local.startpath}/retired.properties") @@ -42,26 +43,28 @@ public class RetiredService { private List<Pattern> retiredAllVersionList; @PostConstruct - public void initialize(){ - this.retiredPatternsList = Arrays.stream(retiredPatterns.split(",")).map(Pattern::compile).collect(Collectors.toList()); - this.retiredAllVersionList = Arrays.stream(retiredAllVersions.split(",")).map(Pattern::compile).collect(Collectors.toList()); + public void initialize() { + this.retiredPatternsList = Arrays.stream(retiredPatterns.split(",")).map(Pattern::compile) + .collect(Collectors.toList()); + this.retiredAllVersionList = Arrays.stream(retiredAllVersions.split(",")) + .map(Pattern::compile).collect(Collectors.toList()); } @Value("${retired.api.pattern.list}") - public void setRetiredPatterns(String retiredPatterns){ + public void setRetiredPatterns(String retiredPatterns) { this.retiredPatterns = retiredPatterns; } - public List<Pattern> getRetiredPatterns(){ + public List<Pattern> getRetiredPatterns() { return retiredPatternsList; } @Value("${retired.api.all.versions}") - public void setRetiredAllVersions(String retiredPatterns){ + public void setRetiredAllVersions(String retiredPatterns) { this.retiredAllVersions = retiredPatterns; } - public List<Pattern> getRetiredAllVersionList(){ + public List<Pattern> getRetiredAllVersionList() { return retiredAllVersionList; } } diff --git a/aai-traversal/src/main/java/org/onap/aai/transforms/Converter.java b/aai-traversal/src/main/java/org/onap/aai/transforms/Converter.java index 676c910..1fe66fe 100644 --- a/aai-traversal/src/main/java/org/onap/aai/transforms/Converter.java +++ b/aai-traversal/src/main/java/org/onap/aai/transforms/Converter.java @@ -8,7 +8,7 @@ * 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 + * 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, diff --git a/aai-traversal/src/main/java/org/onap/aai/transforms/LowerCamelToLowerHyphenConverter.java b/aai-traversal/src/main/java/org/onap/aai/transforms/LowerCamelToLowerHyphenConverter.java index aae42b5..6387deb 100644 --- a/aai-traversal/src/main/java/org/onap/aai/transforms/LowerCamelToLowerHyphenConverter.java +++ b/aai-traversal/src/main/java/org/onap/aai/transforms/LowerCamelToLowerHyphenConverter.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -25,7 +25,7 @@ public class LowerCamelToLowerHyphenConverter implements Converter { @Override public String convert(String input) { - if(input == null){ + if (input == null) { return null; } return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, input); diff --git a/aai-traversal/src/main/java/org/onap/aai/transforms/LowerHyphenToLowerCamelConverter.java b/aai-traversal/src/main/java/org/onap/aai/transforms/LowerHyphenToLowerCamelConverter.java index b4baa0c..804326f 100644 --- a/aai-traversal/src/main/java/org/onap/aai/transforms/LowerHyphenToLowerCamelConverter.java +++ b/aai-traversal/src/main/java/org/onap/aai/transforms/LowerHyphenToLowerCamelConverter.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -24,10 +24,10 @@ package org.onap.aai.transforms; * for converting from the lower hyphen to lower camel case * <p> * Examples: - * lower-test => lowerTest - * lower-Test => lowerTest - * lowerTest => lowerTest - * lower-test-val => lowerTestVal + * lower-test => lowerTest + * lower-Test => lowerTest + * lowerTest => lowerTest + * lower-test-val => lowerTestVal * <p> * */ @@ -46,11 +46,11 @@ public class LowerHyphenToLowerCamelConverter implements Converter { * * @param input the input string to convert to camel case * @return a string that is converted to camel case - * if the input is null, then it returns null + * if the input is null, then it returns null */ @Override public String convert(String input) { - if(input == null){ + if (input == null) { return null; } @@ -59,17 +59,17 @@ public class LowerHyphenToLowerCamelConverter implements Converter { boolean isPreviousCharDash = false; - for(int index = 0; index < size; ++index){ + for (int index = 0; index < size; ++index) { char ch = input.charAt(index); - if(ch == '-'){ + if (ch == '-') { isPreviousCharDash = true; continue; } - if(isPreviousCharDash){ + if (isPreviousCharDash) { builder.append(Character.toUpperCase(ch)); isPreviousCharDash = false; - } else{ + } else { builder.append(ch); } } diff --git a/aai-traversal/src/main/java/org/onap/aai/transforms/MapTraverser.java b/aai-traversal/src/main/java/org/onap/aai/transforms/MapTraverser.java index f59fb10..24d5a83 100644 --- a/aai-traversal/src/main/java/org/onap/aai/transforms/MapTraverser.java +++ b/aai-traversal/src/main/java/org/onap/aai/transforms/MapTraverser.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,23 +19,22 @@ */ package org.onap.aai.transforms; - -import joptsimple.internal.Objects; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import joptsimple.internal.Objects; + public class MapTraverser { private Converter converter; - public MapTraverser(Converter converter){ + public MapTraverser(Converter converter) { this.converter = converter; } - public Map<String, Object> convertKeys(Map<String, Object> map){ + public Map<String, Object> convertKeys(Map<String, Object> map) { Objects.ensureNotNull(map); @@ -45,15 +44,16 @@ public class MapTraverser { return modifiedMap; } - private Map<String, Object> convertKeys(Map<String, Object> original, Map<String, Object> modified){ + private Map<String, Object> convertKeys(Map<String, Object> original, + Map<String, Object> modified) { - for(Map.Entry<String, Object> entry : original.entrySet()){ + for (Map.Entry<String, Object> entry : original.entrySet()) { String key = entry.getKey(); key = converter.convert(key); Object value = entry.getValue(); - if(value instanceof Map){ + if (value instanceof Map) { modified.put(key, convertKeys((Map<String, Object>) value, new HashMap<>())); - } else if(value instanceof List){ + } else if (value instanceof List) { modified.put(key, convertKeys((List<Object>) value)); } else { modified.put(key, value); @@ -63,16 +63,16 @@ public class MapTraverser { return modified; } - public List<Object> convertKeys(List<Object> list){ + public List<Object> convertKeys(List<Object> list) { List<Object> modifiedList = new ArrayList<>(); - if(list != null && !list.isEmpty()){ + if (list != null && !list.isEmpty()) { - for(Object o : list){ - if(o instanceof Map){ + for (Object o : list) { + if (o instanceof Map) { Map<String, Object> map = (Map<String, Object>) o; modifiedList.add(convertKeys(map)); - } else if(o instanceof List){ + } else if (o instanceof List) { List<Object> l = (List<Object>) o; modifiedList.add(convertKeys(l)); } else { diff --git a/aai-traversal/src/main/java/org/onap/aai/util/GenericQueryBuilder.java b/aai-traversal/src/main/java/org/onap/aai/util/GenericQueryBuilder.java index 8570fe4..82ccc73 100644 --- a/aai-traversal/src/main/java/org/onap/aai/util/GenericQueryBuilder.java +++ b/aai-traversal/src/main/java/org/onap/aai/util/GenericQueryBuilder.java @@ -19,11 +19,13 @@ */ package org.onap.aai.util; -import javax.ws.rs.core.HttpHeaders; import java.util.List; + +import javax.ws.rs.core.HttpHeaders; + import org.onap.aai.introspection.Loader; -import org.onap.aai.serialization.queryformats.utils.UrlBuilder; import org.onap.aai.serialization.engines.TransactionalGraphEngine; +import org.onap.aai.serialization.queryformats.utils.UrlBuilder; /** * Builder Class used to minimize number of formal parameters. diff --git a/aai-traversal/src/main/java/org/onap/aai/util/MakeNamedQuery.java b/aai-traversal/src/main/java/org/onap/aai/util/MakeNamedQuery.java index 17207f3..7bda3bb 100644 --- a/aai-traversal/src/main/java/org/onap/aai/util/MakeNamedQuery.java +++ b/aai-traversal/src/main/java/org/onap/aai/util/MakeNamedQuery.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -18,15 +18,14 @@ * ============LICENSE_END========================================================= */ package org.onap.aai.util; -import java.io.File; +import com.att.eelf.configuration.EELFManager; + +import java.io.File; import java.nio.charset.Charset; import java.util.*; import java.util.Map.Entry; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.att.eelf.configuration.EELFManager; import org.apache.commons.io.FileUtils; import org.onap.aai.config.SpringContextAware; import org.onap.aai.introspection.Introspector; @@ -36,217 +35,230 @@ import org.onap.aai.introspection.ModelType; import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.onap.aai.setup.SchemaVersion; import org.onap.aai.setup.SchemaVersions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MakeNamedQuery { - - private static final Logger logger = LoggerFactory.getLogger(MakeNamedQuery.class.getName()); - - public static void main(String[] args) throws Exception { - String _apiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP); - String widgetJsonDir = null; - String modelVersion = null; - String namedQueryUuid = UUID.randomUUID().toString(); - if (args.length > 0) { - if (args[0] != null) { - _apiVersion = args[0]; - } - if (args[1] != null) { - widgetJsonDir = args[1]; - } - if (args[2] != null) { - modelVersion = args[2]; - } - if (args[3] != null) { - namedQueryUuid = args[3]; - } - } - - if (widgetJsonDir == null) { - System.err.println("You must specify a directory for widgetModelJson"); - System.exit(0); - } - if (modelVersion == null) { - System.err.println("You must specify a modelVersion"); - System.exit(0); - } - - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext( - "org.onap.aai.config", - "org.onap.aai.setup" - ); - - LoaderFactory loaderFactory = ctx.getBean(LoaderFactory.class); - SchemaVersions schemaVersions = ctx.getBean(SchemaVersions.class); - - if(schemaVersions.getVersions().contains(_apiVersion)){ - - Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, new SchemaVersion(_apiVersion)); - - // iterate the collection of resources - - ArrayList<String> processedWidgets = new ArrayList<>(); - - - HashMap<String, List<Introspector>> widgetToRelationship = new HashMap<>(); - for (Entry<String, Introspector> aaiResEnt : loader.getAllObjects().entrySet()) { - Introspector meObject; - // no need for a ModelVers DynamicEntity - - Introspector aaiRes = aaiResEnt.getValue(); - - if (!(aaiRes.isContainer() || aaiRes.getName().equals("aai-internal"))) { - String resource = aaiRes.getName(); - - if (processedWidgets.contains(resource)) { - continue; - } - processedWidgets.add(resource); - - String widgetName = resource; - String filePathString = widgetJsonDir + "/" + widgetName + "-" + modelVersion + ".json"; - File f = new File(filePathString); - if (f.exists()) { - System.out.println(f.toString()); - String json = FileUtils.readFileToString(f, Charset.defaultCharset()); - - meObject = loader.unmarshal("Model", json); - String modelInvariantId = meObject.getValue("model-invariant-id"); - if (meObject.hasProperty("model-vers")) { - Introspector modelVers = meObject.getWrappedValue("model-vers"); - List<Introspector> modelVerList = modelVers.getWrappedListValue("model-ver"); - for (Introspector modelVer : modelVerList) { - - List<Introspector> relList = new ArrayList<>(); - Introspector widgetRelationship = makeWidgetRelationship(loader, modelInvariantId, - modelVer.getValue("model-version-id").toString()); - relList.add(widgetRelationship); - - widgetToRelationship.put(widgetName, relList); - } - } - } - } - } - - //source vnf-id, related service-instance-id, all related vnfs in this service-instance-id - //this should be abstracted and moved to a file - - List<Introspector> genericVnfRelationship = widgetToRelationship.get("generic-vnf"); - List<Introspector> vserverRelationship = widgetToRelationship.get("vserver"); - List<Introspector> tenantRelationship = widgetToRelationship.get("tenant"); - List<Introspector> cloudRegionRelationship = widgetToRelationship.get("cloud-region"); - List<Introspector> esrSystemInfoRelationship = widgetToRelationship.get("esr-system-info"); - - Introspector namedQueryObj = loader.introspectorFromName("named-query"); - namedQueryObj.setValue("named-query-uuid", namedQueryUuid); - namedQueryObj.setValue("named-query-name", "vnf-to-esr-system-info"); - namedQueryObj.setValue("named-query-version", "1.0"); - namedQueryObj.setValue("description", "Named Query - VNF to ESR System Info"); - - Introspector genericVnfNQE = setupNQElements(namedQueryObj, genericVnfRelationship); - - Introspector vserverNQE = setupNQElements(genericVnfNQE, vserverRelationship); - - Introspector tenantNQE = setupNQElements(vserverNQE, tenantRelationship); - - Introspector cloudRegionNQE = setupNQElements(tenantNQE, cloudRegionRelationship); - - Introspector esrSystemInfoNQE = setupNQElements(cloudRegionNQE, esrSystemInfoRelationship); - - System.out.println(namedQueryObj.marshal(true)); - - } - - System.exit(0); - - } - - private static Introspector setupNQElements (Introspector nqeObj, List<Introspector> listOfRelationships) { - Introspector newNQElement = null; - try { - Introspector newNQElements = null; - List<Object> nqElementList = null; - if (nqeObj.getWrappedValue("named-query-elements") != null) { - newNQElements = nqeObj.getWrappedValue("named-query-elements"); - nqElementList = newNQElements.getValue("named-query-element"); - } else { - newNQElements = nqeObj.newIntrospectorInstanceOfProperty("named-query-elements"); - nqeObj.setValue("named-query-elements", newNQElements.getUnderlyingObject()); - nqElementList = newNQElements.getValue("named-query-element"); - } - newNQElement = loadNQElement(newNQElements, listOfRelationships); - if (newNQElement != null) { - nqElementList.add(newNQElement.getUnderlyingObject()); - } - - } catch (AAIUnknownObjectException e) { - logger.info("AAIUnknownObjectException in MakeNamedQuery.setupNQElements() "+e); - e.printStackTrace(); - } catch (IllegalArgumentException e) { - logger.info("IllegalArgumentException in MakeNamedQuery.setupNQElements() "+e); - e.printStackTrace(); - } - return newNQElement; - } - - private static Introspector loadNQElement (Introspector nqElements, List<Introspector> listOfRelationships) { - Introspector newNqElement = null; - try { - newNqElement = nqElements.getLoader().introspectorFromName("named-query-element"); - - //newNqElement.setValue("named-query-element-uuid", UUID.randomUUID().toString()); - - Introspector newRelationshipList = newNqElement.getLoader().introspectorFromName("relationship-list"); - newNqElement.setValue("relationship-list", newRelationshipList.getUnderlyingObject()); - - List<Object> newRelationshipListList = newRelationshipList.getValue("relationship"); - - for (Introspector rel : listOfRelationships) { - newRelationshipListList.add(rel.getUnderlyingObject()); - } - - } catch (AAIUnknownObjectException e) { - logger.info("AAIUnknownObjectException in MakeNamedQuery.loadNQElement() "+e); - e.printStackTrace(); - } catch (IllegalArgumentException e) { - logger.info("IllegalArgumentException in MakeNamedQuery.loadNQElement() "+e); - e.printStackTrace(); - } - return newNqElement; - - } - private static Introspector makeWidgetRelationship(Loader loader, String modelInvariantId, String modelVersionId) { - - Introspector newRelationship = null; - try { - newRelationship = loader.introspectorFromName("relationship"); - - List<Object> newRelationshipData = newRelationship.getValue("relationship-data"); - - newRelationship.setValue("related-to", "model"); - - Introspector newRelationshipDatum1 = newRelationship.getLoader().introspectorFromName("relationship-data"); - Introspector newRelationshipDatum2 = newRelationship.getLoader().introspectorFromName("relationship-data"); - - - newRelationshipDatum1.setValue("relationship-key", "model.model-invariant-id"); - newRelationshipDatum1.setValue("relationship-value", modelInvariantId); - - //newRelationshipDatum2.setValue("relationship-key", "model-ver.model-version-id"); - //newRelationshipDatum2.setValue("relationship-value", modelVersionId); - - newRelationshipData.add(newRelationshipDatum1.getUnderlyingObject()); - //newRelationshipData.add(newRelationshipDatum2.getUnderlyingObject()); - } catch (AAIUnknownObjectException e) { - logger.info("AAIUnknownObjectException in MakeNamedQuery.makeWidgetRelationship() "+e); - e.printStackTrace(); - } catch (IllegalArgumentException e) { - logger.info("IllegalArgumentException in MakeNamedQuery.makeWidgetRelationship() "+e); - e.printStackTrace(); - } - - return newRelationship; - } - -}
\ No newline at end of file + + private static final Logger logger = LoggerFactory.getLogger(MakeNamedQuery.class.getName()); + + public static void main(String[] args) throws Exception { + String _apiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP); + String widgetJsonDir = null; + String modelVersion = null; + String namedQueryUuid = UUID.randomUUID().toString(); + if (args.length > 0) { + if (args[0] != null) { + _apiVersion = args[0]; + } + if (args[1] != null) { + widgetJsonDir = args[1]; + } + if (args[2] != null) { + modelVersion = args[2]; + } + if (args[3] != null) { + namedQueryUuid = args[3]; + } + } + + if (widgetJsonDir == null) { + System.err.println("You must specify a directory for widgetModelJson"); + System.exit(0); + } + if (modelVersion == null) { + System.err.println("You must specify a modelVersion"); + System.exit(0); + } + + AnnotationConfigApplicationContext ctx = + new AnnotationConfigApplicationContext("org.onap.aai.config", "org.onap.aai.setup"); + + LoaderFactory loaderFactory = ctx.getBean(LoaderFactory.class); + SchemaVersions schemaVersions = ctx.getBean(SchemaVersions.class); + + if (schemaVersions.getVersions().contains(_apiVersion)) { + + Loader loader = loaderFactory.createLoaderForVersion(ModelType.MOXY, + new SchemaVersion(_apiVersion)); + + // iterate the collection of resources + + ArrayList<String> processedWidgets = new ArrayList<>(); + + HashMap<String, List<Introspector>> widgetToRelationship = new HashMap<>(); + for (Entry<String, Introspector> aaiResEnt : loader.getAllObjects().entrySet()) { + Introspector meObject; + // no need for a ModelVers DynamicEntity + + Introspector aaiRes = aaiResEnt.getValue(); + + if (!(aaiRes.isContainer() || aaiRes.getName().equals("aai-internal"))) { + String resource = aaiRes.getName(); + + if (processedWidgets.contains(resource)) { + continue; + } + processedWidgets.add(resource); + + String widgetName = resource; + String filePathString = + widgetJsonDir + "/" + widgetName + "-" + modelVersion + ".json"; + File f = new File(filePathString); + if (f.exists()) { + System.out.println(f.toString()); + String json = FileUtils.readFileToString(f, Charset.defaultCharset()); + + meObject = loader.unmarshal("Model", json); + String modelInvariantId = meObject.getValue("model-invariant-id"); + if (meObject.hasProperty("model-vers")) { + Introspector modelVers = meObject.getWrappedValue("model-vers"); + List<Introspector> modelVerList = + modelVers.getWrappedListValue("model-ver"); + for (Introspector modelVer : modelVerList) { + + List<Introspector> relList = new ArrayList<>(); + Introspector widgetRelationship = + makeWidgetRelationship(loader, modelInvariantId, + modelVer.getValue("model-version-id").toString()); + relList.add(widgetRelationship); + + widgetToRelationship.put(widgetName, relList); + } + } + } + } + } + + // source vnf-id, related service-instance-id, all related vnfs in this + // service-instance-id + // this should be abstracted and moved to a file + + List<Introspector> genericVnfRelationship = widgetToRelationship.get("generic-vnf"); + List<Introspector> vserverRelationship = widgetToRelationship.get("vserver"); + List<Introspector> tenantRelationship = widgetToRelationship.get("tenant"); + List<Introspector> cloudRegionRelationship = widgetToRelationship.get("cloud-region"); + List<Introspector> esrSystemInfoRelationship = + widgetToRelationship.get("esr-system-info"); + + Introspector namedQueryObj = loader.introspectorFromName("named-query"); + namedQueryObj.setValue("named-query-uuid", namedQueryUuid); + namedQueryObj.setValue("named-query-name", "vnf-to-esr-system-info"); + namedQueryObj.setValue("named-query-version", "1.0"); + namedQueryObj.setValue("description", "Named Query - VNF to ESR System Info"); + + Introspector genericVnfNQE = setupNQElements(namedQueryObj, genericVnfRelationship); + + Introspector vserverNQE = setupNQElements(genericVnfNQE, vserverRelationship); + + Introspector tenantNQE = setupNQElements(vserverNQE, tenantRelationship); + + Introspector cloudRegionNQE = setupNQElements(tenantNQE, cloudRegionRelationship); + + Introspector esrSystemInfoNQE = + setupNQElements(cloudRegionNQE, esrSystemInfoRelationship); + + System.out.println(namedQueryObj.marshal(true)); + + } + + System.exit(0); + + } + + private static Introspector setupNQElements(Introspector nqeObj, + List<Introspector> listOfRelationships) { + Introspector newNQElement = null; + try { + Introspector newNQElements = null; + List<Object> nqElementList = null; + if (nqeObj.getWrappedValue("named-query-elements") != null) { + newNQElements = nqeObj.getWrappedValue("named-query-elements"); + nqElementList = newNQElements.getValue("named-query-element"); + } else { + newNQElements = nqeObj.newIntrospectorInstanceOfProperty("named-query-elements"); + nqeObj.setValue("named-query-elements", newNQElements.getUnderlyingObject()); + nqElementList = newNQElements.getValue("named-query-element"); + } + newNQElement = loadNQElement(newNQElements, listOfRelationships); + if (newNQElement != null) { + nqElementList.add(newNQElement.getUnderlyingObject()); + } + + } catch (AAIUnknownObjectException e) { + logger.info("AAIUnknownObjectException in MakeNamedQuery.setupNQElements() " + e); + e.printStackTrace(); + } catch (IllegalArgumentException e) { + logger.info("IllegalArgumentException in MakeNamedQuery.setupNQElements() " + e); + e.printStackTrace(); + } + return newNQElement; + } + + private static Introspector loadNQElement(Introspector nqElements, + List<Introspector> listOfRelationships) { + Introspector newNqElement = null; + try { + newNqElement = nqElements.getLoader().introspectorFromName("named-query-element"); + + // newNqElement.setValue("named-query-element-uuid", UUID.randomUUID().toString()); + + Introspector newRelationshipList = + newNqElement.getLoader().introspectorFromName("relationship-list"); + newNqElement.setValue("relationship-list", newRelationshipList.getUnderlyingObject()); + + List<Object> newRelationshipListList = newRelationshipList.getValue("relationship"); + + for (Introspector rel : listOfRelationships) { + newRelationshipListList.add(rel.getUnderlyingObject()); + } + + } catch (AAIUnknownObjectException e) { + logger.info("AAIUnknownObjectException in MakeNamedQuery.loadNQElement() " + e); + e.printStackTrace(); + } catch (IllegalArgumentException e) { + logger.info("IllegalArgumentException in MakeNamedQuery.loadNQElement() " + e); + e.printStackTrace(); + } + return newNqElement; + + } + + private static Introspector makeWidgetRelationship(Loader loader, String modelInvariantId, + String modelVersionId) { + + Introspector newRelationship = null; + try { + newRelationship = loader.introspectorFromName("relationship"); + + List<Object> newRelationshipData = newRelationship.getValue("relationship-data"); + + newRelationship.setValue("related-to", "model"); + + Introspector newRelationshipDatum1 = + newRelationship.getLoader().introspectorFromName("relationship-data"); + Introspector newRelationshipDatum2 = + newRelationship.getLoader().introspectorFromName("relationship-data"); + + newRelationshipDatum1.setValue("relationship-key", "model.model-invariant-id"); + newRelationshipDatum1.setValue("relationship-value", modelInvariantId); + + // newRelationshipDatum2.setValue("relationship-key", "model-ver.model-version-id"); + // newRelationshipDatum2.setValue("relationship-value", modelVersionId); + + newRelationshipData.add(newRelationshipDatum1.getUnderlyingObject()); + // newRelationshipData.add(newRelationshipDatum2.getUnderlyingObject()); + } catch (AAIUnknownObjectException e) { + logger + .info("AAIUnknownObjectException in MakeNamedQuery.makeWidgetRelationship() " + e); + e.printStackTrace(); + } catch (IllegalArgumentException e) { + logger.info("IllegalArgumentException in MakeNamedQuery.makeWidgetRelationship() " + e); + e.printStackTrace(); + } + + return newRelationship; + } + +} diff --git a/aai-traversal/src/main/java/org/onap/aai/util/NodesQueryBuilder.java b/aai-traversal/src/main/java/org/onap/aai/util/NodesQueryBuilder.java index 978e484..1250270 100644 --- a/aai-traversal/src/main/java/org/onap/aai/util/NodesQueryBuilder.java +++ b/aai-traversal/src/main/java/org/onap/aai/util/NodesQueryBuilder.java @@ -20,10 +20,12 @@ package org.onap.aai.util; -import org.onap.aai.serialization.engines.TransactionalGraphEngine; -import javax.ws.rs.core.HttpHeaders; import java.util.List; + +import javax.ws.rs.core.HttpHeaders; + import org.onap.aai.introspection.Loader; +import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.onap.aai.serialization.queryformats.utils.UrlBuilder; /** 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 fdeefe1..0094bc2 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,23 +20,25 @@ package org.onap.aai.util; public final class TraversalConstants { - public static final int AAI_QUERY_PORT = 8446; - - public static final String AAI_TRAVERSAL_TIMEOUT_LIMIT = "aai.traversal.timeoutlimit"; - public static final String AAI_TRAVERSAL_TIMEOUT_ENABLED = "aai.traversal.timeoutenabled"; - public static final String AAI_TRAVERSAL_TIMEOUT_APP = "aai.traversal.timeout.appspecific"; - - 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 String DSL_MAX_NODE_COUNT = "15"; + public static final int AAI_QUERY_PORT = 8446; + + public static final String AAI_TRAVERSAL_TIMEOUT_LIMIT = "aai.traversal.timeoutlimit"; + public static final String AAI_TRAVERSAL_TIMEOUT_ENABLED = "aai.traversal.timeoutenabled"; + public static final String AAI_TRAVERSAL_TIMEOUT_APP = "aai.traversal.timeout.appspecific"; + + 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 String DSL_MAX_NODE_COUNT = "15"; public static final long HISTORY_MAX_HOURS = 192; - - private TraversalConstants() { - // prevent instantiation - } + + private TraversalConstants() { + // prevent instantiation + } } 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 39aa31c..87d6d8f 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 @@ -8,7 +8,7 @@ * 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 + * 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, @@ -19,7 +19,19 @@ */ package org.onap.aai.web; +import static java.lang.Boolean.parseBoolean; +import static java.util.Comparator.comparingInt; + import com.google.common.collect.Sets; + +import java.lang.reflect.AnnotatedElement; +import java.util.Collection; +import java.util.Comparator; +import java.util.Set; +import java.util.logging.Logger; + +import javax.annotation.Priority; + import org.glassfish.jersey.server.ResourceConfig; import org.onap.aai.rest.*; import org.onap.aai.rest.search.ModelAndNamedQueryRestProvider; @@ -32,21 +44,12 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; -import javax.annotation.Priority; -import java.lang.reflect.AnnotatedElement; -import java.util.Collection; -import java.util.Comparator; -import java.util.Set; -import java.util.logging.Logger; - -import static java.lang.Boolean.parseBoolean; -import static java.util.Comparator.comparingInt; - @Configuration public class JerseyConfiguration { private static final Logger log = Logger.getLogger(JerseyConfiguration.class.getName()); - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(JerseyConfiguration.class.getName()); + private static final org.slf4j.Logger logger = + LoggerFactory.getLogger(JerseyConfiguration.class.getName()); private static final String LOGGING_ENABLED_PROPERTY = "aai.request.logging.enabled"; private static final boolean ENABLE_RESPONSE_LOGGING = false; @@ -62,18 +65,11 @@ public class JerseyConfiguration { public ResourceConfig resourceConfig() { ResourceConfig resourceConfig = new ResourceConfig(); - Set<Class<?>> classes = Sets.newHashSet( - SearchProvider.class, - ModelAndNamedQueryRestProvider.class, - QueryConsumer.class, - RecentAPIConsumer.class, - DslConsumer.class, - EchoResponse.class, - CQ2Gremlin.class, - CQ2GremlinTest.class - ); - Set<Class<?>> filterClasses = Sets.newHashSet( - org.onap.aai.interceptors.pre.RequestTransactionLogging.class, + Set<Class<?>> classes = Sets.newHashSet(SearchProvider.class, + ModelAndNamedQueryRestProvider.class, QueryConsumer.class, RecentAPIConsumer.class, + DslConsumer.class, EchoResponse.class, CQ2Gremlin.class, CQ2GremlinTest.class); + Set<Class<?>> filterClasses = + Sets.newHashSet(org.onap.aai.interceptors.pre.RequestTransactionLogging.class, org.onap.aai.interceptors.pre.HeaderValidation.class, org.onap.aai.interceptors.pre.HttpHeaderInterceptor.class, org.onap.aai.interceptors.pre.OneWaySslAuthorization.class, @@ -84,28 +80,24 @@ public class JerseyConfiguration { org.onap.aai.interceptors.pre.RequestModification.class, org.onap.aai.interceptors.post.InvalidResponseStatus.class, org.onap.aai.interceptors.post.ResponseTransactionLogging.class, - org.onap.aai.interceptors.post.ResponseHeaderManipulation.class - ); + org.onap.aai.interceptors.post.ResponseHeaderManipulation.class); resourceConfig.registerClasses(classes); logger.debug("REGISTERED CLASSES " + classes.toString()); throwIfPriorityAnnotationAbsent(filterClasses); - filterClasses.stream() - .filter(this::isEnabledByActiveProfiles) - .sorted(priorityComparator()) - .forEach(resourceConfig::register); - - filterClasses.stream() - .filter(this::isEnabledByActiveProfiles) - .sorted(priorityComparator()) - .forEach(s -> logger.debug("REGISTERED FILTERS " + s.getName())); + filterClasses.stream().filter(this::isEnabledByActiveProfiles).sorted(priorityComparator()) + .forEach(resourceConfig::register); + + filterClasses.stream().filter(this::isEnabledByActiveProfiles).sorted(priorityComparator()) + .forEach(s -> logger.debug("REGISTERED FILTERS " + s.getName())); return resourceConfig; } private <T> void throwIfPriorityAnnotationAbsent(Collection<Class<? extends T>> classes) { for (Class clazz : classes) { if (!clazz.isAnnotationPresent(Priority.class)) { - logger.debug("throwIfPriorityAnnotationAbsent: missing filter priority for : " + clazz.getName()); + logger.debug("throwIfPriorityAnnotationAbsent: missing filter priority for : " + + clazz.getName()); throw new MissingFilterPriorityException(clazz); } } @@ -120,9 +112,10 @@ public class JerseyConfiguration { } private boolean isEnabledByActiveProfiles(AnnotatedElement annotatedElement) { - boolean result = !annotatedElement.isAnnotationPresent(Profile.class) || - environment.acceptsProfiles(annotatedElement.getAnnotation(Profile.class).value()); - logger.debug("isEnabledByActiveProfiles: annotatedElement: " + annotatedElement.toString() + " result=" + result); + boolean result = !annotatedElement.isAnnotationPresent(Profile.class) + || environment.acceptsProfiles(annotatedElement.getAnnotation(Profile.class).value()); + logger.debug("isEnabledByActiveProfiles: annotatedElement: " + annotatedElement.toString() + + " result=" + result); return result; } @@ -131,4 +124,4 @@ public class JerseyConfiguration { super("Container filter " + clazz.getName() + " does not have @Priority annotation"); } } -}
\ No newline at end of file +} diff --git a/aai-traversal/src/main/java/org/onap/aai/web/LocalHostAccessLog.java b/aai-traversal/src/main/java/org/onap/aai/web/LocalHostAccessLog.java index d2a4e89..cea7fc5 100644 --- a/aai-traversal/src/main/java/org/onap/aai/web/LocalHostAccessLog.java +++ b/aai-traversal/src/main/java/org/onap/aai/web/LocalHostAccessLog.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -20,6 +20,9 @@ package org.onap.aai.web; import ch.qos.logback.access.jetty.RequestLogImpl; + +import java.util.Arrays; + import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.util.thread.QueuedThreadPool; @@ -29,39 +32,37 @@ import org.springframework.boot.web.servlet.server.AbstractServletWebServerFacto import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Arrays; - @Configuration public class LocalHostAccessLog { @Bean public AbstractServletWebServerFactory jettyConfigBean( - @Value("${jetty.threadPool.maxThreads:200}") final String maxThreads, - @Value("${jetty.threadPool.minThreads:8}") final String minThreads - ){ + @Value("${jetty.threadPool.maxThreads:200}") final String maxThreads, + @Value("${jetty.threadPool.minThreads:8}") final String minThreads) { JettyServletWebServerFactory jef = new JettyServletWebServerFactory(); - jef.addServerCustomizers((org.springframework.boot.web.embedded.jetty.JettyServerCustomizer) server -> { + jef.addServerCustomizers( + (org.springframework.boot.web.embedded.jetty.JettyServerCustomizer) server -> { - HandlerCollection handlers = new HandlerCollection(); + HandlerCollection handlers = new HandlerCollection(); - Arrays.stream(server.getHandlers()).forEach(handlers::addHandler); + Arrays.stream(server.getHandlers()).forEach(handlers::addHandler); - RequestLogHandler requestLogHandler = new RequestLogHandler(); - requestLogHandler.setServer(server); + RequestLogHandler requestLogHandler = new RequestLogHandler(); + requestLogHandler.setServer(server); - RequestLogImpl requestLogImpl = new RequestLogImpl(); - requestLogImpl.setResource("/localhost-access-logback.xml"); - requestLogImpl.start(); + RequestLogImpl requestLogImpl = new RequestLogImpl(); + requestLogImpl.setResource("/localhost-access-logback.xml"); + requestLogImpl.start(); - requestLogHandler.setRequestLog(requestLogImpl); - handlers.addHandler(requestLogHandler); - server.setHandler(handlers); + requestLogHandler.setRequestLog(requestLogImpl); + handlers.addHandler(requestLogHandler); + server.setHandler(handlers); - final QueuedThreadPool threadPool = server.getBean(QueuedThreadPool.class); - threadPool.setMaxThreads(Integer.valueOf(maxThreads)); - threadPool.setMinThreads(Integer.valueOf(minThreads)); - }); + final QueuedThreadPool threadPool = server.getBean(QueuedThreadPool.class); + threadPool.setMaxThreads(Integer.valueOf(maxThreads)); + threadPool.setMinThreads(Integer.valueOf(minThreads)); + }); return jef; } } diff --git a/aai-traversal/src/main/java/org/onap/aai/web/MicrometerConfiguration.java b/aai-traversal/src/main/java/org/onap/aai/web/MicrometerConfiguration.java index 7c93e7d..77dbe96 100644 --- a/aai-traversal/src/main/java/org/onap/aai/web/MicrometerConfiguration.java +++ b/aai-traversal/src/main/java/org/onap/aai/web/MicrometerConfiguration.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -18,23 +18,24 @@ * ============LICENSE_END========================================================= */ package org.onap.aai.web; + import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Tags; import io.micrometer.jersey2.server.JerseyTags; import io.micrometer.jersey2.server.JerseyTagsProvider; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + import org.glassfish.jersey.server.ContainerResponse; import org.glassfish.jersey.server.monitoring.RequestEvent; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** - * Configuration Class to add customized tags to http metrics scraped in /actuator/prometheus endpoint + * Configuration Class to add customized tags to http metrics scraped in /actuator/prometheus + * endpoint */ @Configuration -@ConditionalOnProperty( - value="scrape.uri.metrics", - havingValue = "true") +@ConditionalOnProperty(value = "scrape.uri.metrics", havingValue = "true") public class MicrometerConfiguration { private static final String TAG_AAI_URI = "aai_uri"; private static final String NOT_AVAILABLE = "NOT AVAILABLE"; @@ -46,8 +47,10 @@ public class MicrometerConfiguration { public Iterable httpRequestTags(RequestEvent event) { ContainerResponse response = event.getContainerResponse(); return Tags.of(JerseyTags.method(event.getContainerRequest()), - JerseyTags.exception(event), JerseyTags.status(response), JerseyTags.outcome(response), getAaiUriTag(event)); + JerseyTags.exception(event), JerseyTags.status(response), + JerseyTags.outcome(response), getAaiUriTag(event)); } + private Tag getAaiUriTag(RequestEvent event) { String aai_uri = event.getUriInfo().getRequestUri().toString(); if (aai_uri == null) { @@ -55,9 +58,11 @@ public class MicrometerConfiguration { } return Tag.of(TAG_AAI_URI, aai_uri); } + @Override public Iterable<Tag> httpLongRequestTags(RequestEvent event) { - return Tags.of(JerseyTags.method(event.getContainerRequest()), JerseyTags.uri(event)); + return Tags.of(JerseyTags.method(event.getContainerRequest()), + JerseyTags.uri(event)); } }; } diff --git a/aai-traversal/src/main/java/org/onap/aai/web/WebConfiguration.java b/aai-traversal/src/main/java/org/onap/aai/web/WebConfiguration.java index 5300611..a2a4271 100644 --- a/aai-traversal/src/main/java/org/onap/aai/web/WebConfiguration.java +++ b/aai-traversal/src/main/java/org/onap/aai/web/WebConfiguration.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -27,20 +27,16 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter @Configuration public class WebConfiguration { - @Bean - public WebMvcConfigurerAdapter forwardToIndex() { - return new WebMvcConfigurerAdapter() { - @Override - public void addViewControllers(ViewControllerRegistry registry) { - registry.addViewController("/swagger").setViewName( - "redirect:/swagger/index.html"); - registry.addViewController("/swagger/").setViewName( - "redirect:/swagger/index.html"); - registry.addViewController("/docs").setViewName( - "redirect:/docs/html/index.html"); - registry.addViewController("/docs/").setViewName( - "redirect:/docs/html/index.html"); - } - }; - } -}
\ No newline at end of file + @Bean + public WebMvcConfigurerAdapter forwardToIndex() { + return new WebMvcConfigurerAdapter() { + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/swagger").setViewName("redirect:/swagger/index.html"); + registry.addViewController("/swagger/").setViewName("redirect:/swagger/index.html"); + registry.addViewController("/docs").setViewName("redirect:/docs/html/index.html"); + registry.addViewController("/docs/").setViewName("redirect:/docs/html/index.html"); + } + }; + } +} |