diff options
Diffstat (limited to 'aai-traversal/src/main/java/org')
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"); + } + }; + } +} |